diff --git a/Changes.md b/Changes.md
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,11 @@
 # Change log for the `synthesizer-llvm` package
 
+## 1.0
+
+* Move from `llvm-dsl` `Parameter` to `Exp` for parameters.
+  Remove clumsy distinction between simple and parameterized
+  `Signal`s and `Process`es.
+
 ## 0.9
 
 * Clean separation between Haskell's `Storable` memory format
diff --git a/alsa/Synthesizer/LLVM/Server/CausalPacked/Run.hs b/alsa/Synthesizer/LLVM/Server/CausalPacked/Run.hs
--- a/alsa/Synthesizer/LLVM/Server/CausalPacked/Run.hs
+++ b/alsa/Synthesizer/LLVM/Server/CausalPacked/Run.hs
@@ -20,10 +20,12 @@
 import qualified Synthesizer.ALSA.CausalIO.Process as PAlsa
 import qualified Synthesizer.CausalIO.Process as PIO
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Process as Causal
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 
 import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 
 import qualified Data.StorableVector as SV
 
@@ -34,8 +36,7 @@
 import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
 import qualified Sound.MIDI.Message.Channel as ChannelMsg
 
-import Control.Arrow ((<<<), (^<<), arr)
-import Control.Category (id)
+import Control.Arrow (arr, (<<<), (^<<), (<<^))
 
 import qualified Number.DimensionTerm as DN
 
@@ -75,7 +76,7 @@
    opt <- Option.get
    proc <-
       Arrange.keyboardFM
-         (CausalP.mapSimple StereoInt.interleave)
+         (Causal.map StereoInt.interleave)
          (Option.channel opt)
    playFromEvents opt $ \ sampleRate ->
       SigStL.unpackStereoStrict ^<< proc sampleRate
@@ -87,7 +88,7 @@
        PIO.T (MIO.Events Event.T) (SV.Vector StereoVector))
 keyboardDetuneFMCore opt =
    Arrange.keyboardDetuneFMCore
-      (CausalP.mapSimple StereoInt.interleave)
+      (Causal.map StereoInt.interleave)
       (Option.sampleDirectory opt)
 
 keyboardDetuneFM :: IO ()
@@ -111,7 +112,7 @@
    opt <- Option.get
    proc <-
       Arrange.voderBand
-         (CausalP.mapSimple StereoInt.interleave)
+         (Causal.map StereoInt.interleave)
          (Option.sampleDirectory opt)
 
    playFromEvents opt $ \ sampleRate ->
@@ -124,7 +125,7 @@
    opt <- Option.get
    proc <-
       Arrange.voderMask
-         (CausalP.mapSimple StereoInt.interleave)
+         (Causal.map StereoInt.interleave)
          (Option.sampleDirectory opt)
 
    playFromEvents opt $ \ sampleRate ->
@@ -137,7 +138,7 @@
    opt <- Option.get
    proc <-
       Arrange.voderMaskEnv
-         (CausalP.mapSimple StereoInt.interleave)
+         (Causal.map StereoInt.interleave)
          (Option.sampleDirectory opt)
 
    playFromEvents opt $ \ sampleRate ->
@@ -150,7 +151,7 @@
    opt <- Option.get
    proc <-
       Arrange.voderMaskSeparated
-         (CausalP.mapSimple StereoInt.interleave)
+         (const $ Causal.map StereoInt.interleave)
          (Option.sampleDirectory opt)
 
    playFromEvents opt $ \ sampleRate ->
@@ -158,7 +159,7 @@
       <<<
       proc
          (Option.channel opt) (Option.extraChannel opt)
-         (VoiceMsg.toProgram 4) sampleRate
+         (VoiceMsg.toProgram 4) sampleRate ()
 
 voderMaskMulti :: IO ()
 voderMaskMulti = do
@@ -171,21 +172,21 @@
 formant = do
    opt <- Option.get
    proc <-
-      Arrange.keyboardDetuneFMCore id
+      Arrange.keyboardDetuneFMCore (arr Stereo.multiValue)
          (Option.sampleDirectory opt)
    form <- Speech.filterFormant
-   mix <- CausalP.processIO CausalP.mix
+   mix <- CausalRender.run Causal.mix
    interleave <-
-      CausalP.processIO
-         (CausalP.mapSimple StereoInt.interleave)
+      CausalRender.run
+         (Causal.map StereoInt.interleave <<^ Stereo.unMultiValue)
 
    playFromEvents opt $ \ sampleRate ->
       arr SigStL.unpackStereoStrict
       <<<
-      interleave ()
+      interleave
       <<<
       foldl1
-         (\x y -> mix () <<< Zip.arrowFanout x y)
+         (\x y -> mix <<< Zip.arrowFanout x y)
          (zipWith
              (\n (freq, amp, reson) ->
                 form sampleRate
diff --git a/alsa/Synthesizer/LLVM/Server/CausalPacked/Test.hs b/alsa/Synthesizer/LLVM/Server/CausalPacked/Test.hs
--- a/alsa/Synthesizer/LLVM/Server/CausalPacked/Test.hs
+++ b/alsa/Synthesizer/LLVM/Server/CausalPacked/Test.hs
@@ -6,12 +6,11 @@
 import qualified Synthesizer.LLVM.Server.SampledSound as Sample
 import qualified Synthesizer.LLVM.Server.Option as Option
 import qualified Synthesizer.LLVM.Server.Default as Default
+import Synthesizer.LLVM.Server.CausalPacked.Common (chopEvents)
 import Synthesizer.LLVM.Server.CausalPacked.Arrange
           ((&+&), shortTime, controllerExponentialDim)
-import Synthesizer.LLVM.Server.CommonPacked
-          (Vector)
-import Synthesizer.LLVM.Server.Common hiding
-          (Instrument)
+import Synthesizer.LLVM.Server.CommonPacked (Vector)
+import Synthesizer.LLVM.Server.Common hiding (Instrument)
 
 import qualified Sound.ALSA.Sequencer.Event as Event
 -- import qualified Sound.ALSA.Sequencer.Connect as Connect
@@ -38,15 +37,17 @@
 import qualified Synthesizer.PiecewiseConstant.Signal as PC
 import qualified Synthesizer.CausalIO.Process as PIO
 
-import qualified Synthesizer.LLVM.CausalParameterized.FunctionalPlug as FP
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.FunctionalPlug as FP
+import qualified Synthesizer.LLVM.Causal.Functional as F
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Storable.Process as CausalSt
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
 import qualified Synthesizer.LLVM.Wave as Wave
-import Synthesizer.LLVM.CausalParameterized.Process (($*), ($<))
+import Synthesizer.LLVM.Causal.Process (($*), ($<))
 
 import qualified Synthesizer.Generic.Cut          as CutG
 import qualified Synthesizer.Storable.Cut         as CutSt
@@ -58,11 +59,13 @@
 import qualified Data.EventList.Relative.TimeMixed as EventListTM
 import qualified Data.EventList.Relative.BodyTime  as EventListBT
 
+import qualified LLVM.DSL.Expression as Expr
+
 import System.Path ((</>))
 
-import Control.Arrow ((<<<), (<<^), (^<<), arr, first)
+import Control.Arrow (arr, (***), (<<<), (<<^), (^<<))
 import Control.Category (id)
-import Control.Applicative (pure, liftA2)
+import Control.Applicative (liftA2)
 import Control.Monad (when)
 import Control.Monad.Trans.State (evalState)
 
@@ -75,8 +78,9 @@
 import Data.Word (Word8, Word32)
 import Data.Int (Int32)
 
-import Foreign.Storable (Storable)
+import qualified System.Unsafe as Unsafe
 import qualified System.IO as IO
+import Foreign.Storable (Storable)
 import Control.Exception (bracket)
 
 import Prelude hiding (Real, id)
@@ -229,10 +233,10 @@
    opt <- Option.get
    arrange <- CausalSt.makeArranger
    amp <-
-      CausalP.processIO
-         (CausalP.mapSimple StereoInt.interleave <<<
-          CausalP.envelopeStereo <<<
-          first (CausalP.mapSimple Serial.upsample))
+      CausalRender.run
+         (Causal.map StereoInt.interleave <<<
+          Causal.envelopeStereo <<<
+          Causal.map Serial.upsample *** arr Stereo.unMultiValue)
 
    ping <- Instr.pingStereoReleaseFM
 
@@ -269,7 +273,7 @@
    let proc =
           arr SigStL.unpackStereoStrict
           <<<
-          amp ()
+          amp
           <<<
           (MCS.controllerExponential controllerVolume (0.001, 1) (0.2::Float)
            <<^ Zip.second)
@@ -321,8 +325,8 @@
    opt <- Option.get
 
    amp <-
-      CausalP.processIO
-         (CausalP.mapSimple StereoInt.interleave)
+      CausalRender.run
+         (Causal.map StereoInt.interleave <<^ Stereo.unMultiValue)
 
    tomatoSmps <- makeSampledSounds opt
 
@@ -337,7 +341,7 @@
    writeTest
       (arr SigStL.unpackStereoStrict
        <<<
-       amp ()
+       amp
        <<<
        tomato (last tomatoSmps) 0 440) $
       map
@@ -393,8 +397,8 @@
    opt <- Option.get
 
    amp <-
-      CausalP.processIO
-         (CausalP.mapSimple StereoInt.interleave)
+      CausalRender.run
+         (Causal.map StereoInt.interleave <<^ Stereo.unMultiValue)
 
    tomatoSmps <- makeSampledSounds opt
 
@@ -409,7 +413,7 @@
    writeTest
       (arr SigStL.unpackStereoStrict
        <<<
-       amp ()
+       amp
        <<<
        tomato (head tomatoSmps) 0 440) $
       map
@@ -424,9 +428,9 @@
 
 lfo :: SVL.Vector Real
 lfo =
-   SigP.renderChunky (SVL.chunkSize 512)
-      (1 + 0.1 * SigP.osciSimple Wave.approxSine2 (pure (0::Float)) 0.0001)
-      ()
+   Unsafe.performIO $
+   fmap ($ SVL.chunkSize 512) $
+   Render.run (1 + 0.1 * Sig.osci Wave.approxSine2 Expr.zero 0.0001)
 
 asMono :: vector Real -> vector Real
 asMono = id
@@ -438,10 +442,8 @@
 
    SVL.writeFile "/tmp/test.f32" .
       asMono .
-      (\f -> f smp lfo) =<<
-      CausalP.runStorableChunky
-         (CausalP.frequencyModulationLinear $
-          SigP.fromStorableVectorLazy id)
+      (\f -> pioApply (f smp) lfo) =<<
+      CausalRender.run Causal.frequencyModulationLinear
 
 
 frequencyModulationIO :: IO ()
@@ -449,10 +451,7 @@
    opt <- Option.get
    smp <- loadTomato opt
 
-   proc <-
-      CausalP.processIO
-         (CausalP.frequencyModulationLinear $
-          SigP.fromStorableVectorLazy id)
+   proc <- CausalRender.run Causal.frequencyModulationLinear
 
    writeTest (proc smp :: PIO.T (SV.Vector Real) (SV.Vector Real)) $
       SVL.chunks lfo
@@ -462,10 +461,7 @@
    opt <- Option.get
    smp <- loadTomato opt
 
-   proc <-
-      CausalP.processIO
-         (CausalP.frequencyModulationLinear $
-          SigP.fromStorableVector id)
+   proc <- CausalRender.run Causal.frequencyModulationLinear
 
    writeTest
       (proc (SV.concat $ SVL.chunks smp) ::
@@ -475,9 +471,9 @@
 frequencyModulationSawIO :: IO ()
 frequencyModulationSawIO = do
    proc <-
-      CausalP.processIO
-         (CausalP.frequencyModulationLinear
-             (CausalP.take 50000 $* SigP.osciSaw 0 id))
+      CausalRender.run $ \freq ->
+         Causal.frequencyModulationLinear
+             (Causal.take 50000 $* Sig.osci Wave.saw 0 freq)
 
    writeTest (proc (0.01::Real) :: PIO.T (SV.Vector Real) (SV.Vector Real)) $
       SVL.chunks lfo
@@ -487,9 +483,7 @@
    opt <- Option.get
    smp <- loadTomato opt
 
-   proc <-
-      CausalP.processIO
-         (CausalP.envelope $< SigP.fromStorableVectorLazy id)
+   proc <- CausalRender.run $ \env -> Causal.envelope $< env
 
    writeTest (proc smp :: PIO.T (SV.Vector Real) (SV.Vector Real)) $
       SVL.chunks lfo
@@ -498,14 +492,15 @@
 functional :: IO ()
 functional = do
    phaser <-
-      CausalP.processIO $ F.withArgs $ \ratio ->
-         let freq = frequency id
-             noise = F.fromSignal $ SigP.noise 12 (recip freq)
+      CausalRender.run $
+      wrapped $ \(NoiseReference noiseRef) (SampleRate _sr) ->
+      F.withArgs $ \ratio ->
+         let noise = F.fromSignal $ Sig.noise 12 noiseRef
          in  (1-ratio) * noise +
-             ratio * (CausalP.delayZero 100 F.$& noise)
+             ratio * (Causal.delayZero 100 F.$& noise)
 
    writeTest
-      (phaser (sampleRate, 200000) ::
+      (phaser sampleRate (200000 :: Real) ::
          PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Float)) $
       map (\y -> EventListBT.singleton y 10000)
           [0, 0.25, 0.5, 0.75, 1.00]
@@ -514,12 +509,15 @@
 functionalPlug :: IO ()
 functionalPlug = do
    phaser <-
-      FP.withArgs $ \ratio0 ->
-         let freq = frequency id
-             ratio = FP.plug ratio0
-             noise = FP.fromSignal $ SigP.noise 12 (recip freq)
+      FP.withArgs $ \ratio0 pl ->
+      (\f ->
+         case Expr.unzip pl of
+            (sr,noiseRef) -> f (expSampleRate sr) noiseRef) $
+      wrapped $ \(NoiseReference noiseRef) (SampleRate _sr) ->
+         let ratio = FP.plug ratio0
+             noise = FP.fromSignal $ Sig.noise 12 noiseRef
          in  (1-ratio) * noise +
-             ratio * (CausalP.delayZero 100 FP.$& noise)
+             ratio * (Causal.delayZero 100 FP.$& noise)
 
    writeTest
       (phaser () (sampleRate, 200000) ::
@@ -531,9 +529,9 @@
 makeUnpackStereoStrict ::
    IO (PIO.T (SV.Vector (Stereo.T Vector)) (SV.Vector (Stereo.T Real)))
 makeUnpackStereoStrict =
-   fmap (\proc -> SigStL.unpackStereoStrict ^<< proc ()) $
-   CausalP.processIO
-      (CausalP.mapSimple StereoInt.interleave)
+   fmap (SigStL.unpackStereoStrict ^<<) $
+   CausalRender.run
+      (Causal.map StereoInt.interleave <<^ Stereo.unMultiValue)
 {-
 makeUnpackStereoStrict ::
    IO (SV.Vector (Stereo.T Vector) -> SV.Vector (Stereo.T Real))
diff --git a/alsa/Synthesizer/LLVM/Server/Packed/Run.hs b/alsa/Synthesizer/LLVM/Server/Packed/Run.hs
--- a/alsa/Synthesizer/LLVM/Server/Packed/Run.hs
+++ b/alsa/Synthesizer/LLVM/Server/Packed/Run.hs
@@ -20,14 +20,17 @@
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 
 import qualified Synthesizer.LLVM.Filter.Universal as UniFilterL
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Synthesizer.LLVM.Wave as WaveL
-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*))
-import Synthesizer.LLVM.Parameter (($#))
+import Synthesizer.LLVM.Causal.Process (($<), ($*))
 
+import LLVM.DSL.Expression (Exp)
+
 import qualified Synthesizer.Storable.Signal as SigSt
 import qualified Data.StorableVector.Lazy as SVL
 
@@ -45,7 +48,7 @@
 import qualified System.Path as Path
 
 import qualified Control.Applicative.HT as App
-import Control.Arrow ((<<<), (^<<), arr)
+import Control.Arrow (arr, (<<<), (^<<), (<<^))
 import Control.Applicative (pure, liftA2, liftA3, (<*>))
 import Control.Monad.Trans.State (evalState)
 
@@ -108,13 +111,13 @@
 frequencyModulation = do
    opt <- Option.get
    osc <-
-      SigP.runChunky
-         ((CausalPS.osciSimple WaveL.triangle $< zero)
-           $* Instr.frequencyFromBendModulation
-                 (frequencyConst 10)
-                 (Instr.modulation (\fm -> (fm,880))))
+      Render.run $
+      wrapped $ \(Instr.Modulation fm) ->
+      constant frequency 10 $ \speed _sr ->
+         ((CausalPS.osci WaveL.triangle $< zero)
+           $* Instr.frequencyFromBendModulation speed fm)
    withMIDIEventsMono opt play $ \vectorChunkSize sampleRate ->
-      osc vectorChunkSize . (,) sampleRate .
+      osc vectorChunkSize sampleRate . flip (,) (880::Real) .
       evalState (PC.bendWheelPressure (Option.channel opt) 2 0.04 (0.03::Real))
 
 
@@ -123,10 +126,10 @@
 keyboard = do
    opt <- Option.get
    sound <- Instr.pingRelease $/ 0.4 $/ 0.1
-   amp <- CausalP.runStorableChunky (CausalPS.amplify (arr id))
+   amp <- CausalRender.run CausalPS.amplify
    arrange <- SigStL.makeArranger
    withMIDIEventsMono opt play $ \vectorChunkSize sampleRate ->
-      (amp :: Real -> SigSt.T Vector -> SigSt.T Vector) 0.2 .
+      pioApply (amp (0.2::Real)) .
       arrange vectorChunkSize .
       evalState
          (Gen.sequence (Option.channel opt) $
@@ -137,12 +140,12 @@
    opt <- Option.get
    sound <- Instr.pingStereoRelease $/ 0.4 $/ 0.1
    amp <-
-      CausalP.runStorableChunky
-         (CausalP.mapSimple StereoInt.interleave <<<
-          CausalPS.amplifyStereo (arr id))
+      CausalRender.run $ \vol ->
+         Causal.map StereoInt.interleave <<<
+         CausalPS.amplifyStereo vol <<^ Stereo.unMultiValue
    arrange <- SigStL.makeArranger
    withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->
-      (amp :: Real -> SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) 0.2 .
+      pioApply (amp (0.2 :: Real)) .
       arrange vectorChunkSize .
       evalState
          (Gen.sequence (Option.channel opt) $
@@ -153,12 +156,12 @@
    opt <- Option.get
    str <- Instr.softStringFM
    amp <-
-      CausalP.runStorableChunky
-         (CausalP.mapSimple StereoInt.interleave <<<
-          CausalPS.amplifyStereo (arr id))
+      CausalRender.run $ \vol ->
+         Causal.map StereoInt.interleave <<<
+         CausalPS.amplifyStereo vol <<^ Stereo.unMultiValue
    arrange <- SigStL.makeArranger
    withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->
-      (amp :: Real -> SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) 0.2 .
+      pioApply (amp (0.2 :: Real)) .
       arrange vectorChunkSize .
       evalState
          (do fm <- PC.bendWheelPressure (Option.channel opt) 2 0.04 0.03
@@ -171,12 +174,12 @@
    str <- Instr.softStringFM
    tin <- Instr.tineStereoFM $/ 0.4 $/ 0.1
    amp <-
-      CausalP.runStorableChunky
-         (CausalP.mapSimple StereoInt.interleave <<<
-          CausalPS.amplifyStereo (arr id))
+      CausalRender.run $ \vol ->
+         Causal.map StereoInt.interleave <<<
+         CausalPS.amplifyStereo vol <<^ Stereo.unMultiValue
    arrange <- SigStL.makeArranger
    withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->
-      (amp :: Real -> SigSt.T (Stereo.T Vector) -> SigSt.T StereoVector) 0.2 .
+      pioApply (amp (0.2 :: Real)) .
       arrange vectorChunkSize .
       evalState
          (do fm <- PC.bendWheelPressure (Option.channel opt) 2 0.04 0.03
@@ -240,10 +243,10 @@
 
    arrange <- SigStL.makeArranger
    amp <-
-      CausalP.runStorableChunky
-         (CausalP.mapSimple StereoInt.interleave <<<
-          CausalP.envelopeStereo $<
-            Instr.piecewiseConstantVector (arr id))
+      CausalRender.run $ \ctrl ->
+         (Causal.map StereoInt.interleave <<<
+          Causal.envelopeStereo $< Instr.piecewiseConstantVector ctrl)
+            <<^ Stereo.unMultiValue
    return $ \chan pgm vcsize sr -> do
       let
        evHead =
@@ -421,7 +424,7 @@
 
       ctrls <- PCS.fromChannel chan
 
-      fmap (amp volume . arrange vcsize) $
+      fmap (pioApply (amp volume) . arrange vcsize) $
          Gen.sequenceModulatedMultiProgram
             ctrls chan pgm
             (map (\sound fm -> sound fm $ sr) $
@@ -436,35 +439,38 @@
    opt <- Option.get
    proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)
    withMIDIEventsStereo opt play $ \vectorChunkSize sampleRate ->
-      evalState (proc (Option.channel opt) (VoiceMsg.toProgram 0) vectorChunkSize sampleRate)
+      evalState
+         (proc (Option.channel opt) (VoiceMsg.toProgram 0)
+            vectorChunkSize sampleRate)
 
 keyboardFilter :: IO ()
 keyboardFilter = do
    opt <- Option.get
    proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)
-   mix <- CausalP.runStorableChunky $
+   mix <- CausalRender.run $ \xs ->
       arr id
       +
-      (CausalP.mapSimple (StereoInt.amplify 0.5)
+      (Causal.map (StereoInt.amplify 0.5)
        <<<
-       CausalP.fromSignal (SigP.fromStorableVectorLazy (arr id)))
+       Causal.fromSignal xs)
 
    lowpass0 <-
-      CausalP.runStorableChunky $
-      CausalP.mapSimple StereoInt.interleave
+      CausalRender.run $ \cutoff ->
+      Causal.map StereoInt.interleave
       <<<
 --      CausalPS.amplifyStereo 0.1 <<<
       CausalPS.pack
-         (CausalP.stereoFromMonoControlled
-             (UniFilter.lowpass ^<< UniFilterL.causal) $<
-          (SigP.interpolateConstant $# (fromIntegral vectorSize :: Real))
-             (piecewiseConstant (arr id)))
+         (Causal.stereoFromMonoControlled
+             (UniFilter.lowpass ^<< UniFilterL.causalExp) $<
+          Sig.interpolateConstant (fromIntegral vectorSize :: Exp Int)
+             (UniFilterL.unMultiValueParameter <$> piecewiseConstant cutoff))
       <<<
-      CausalP.mapSimple StereoInt.deinterleave
+      Causal.map StereoInt.deinterleave
    let lowpass ::
           Option.SampleRate Real -> PC.T Real -> PC.T Real ->
           SigSt.T StereoVector -> SigSt.T StereoVector
        lowpass (Option.SampleRate sr) resons freqs =
+          pioApply $
           lowpass0 $ fmap UniFilter.parameter $
           PC.zipWith FiltR.Pole resons $ fmap (/ sr) freqs
 
@@ -490,5 +496,5 @@
                 proc (Option.channel opt) (VoiceMsg.toProgram 0)
                    vectorChunkSize sampleRate
              return
-                (pureMusic `mix`
+                (pioApply (mix pureMusic) $
                  lowpass sampleRate resonance freq filterMusic))
diff --git a/alsa/Synthesizer/LLVM/Server/Packed/Test.hs b/alsa/Synthesizer/LLVM/Server/Packed/Test.hs
--- a/alsa/Synthesizer/LLVM/Server/Packed/Test.hs
+++ b/alsa/Synthesizer/LLVM/Server/Packed/Test.hs
@@ -3,29 +3,29 @@
 import qualified Synthesizer.LLVM.Server.Packed.Instrument as Instr
 import qualified Synthesizer.LLVM.Server.Default as Default
 import qualified Synthesizer.LLVM.Server.SampledSound as Sample
+import Synthesizer.LLVM.Server.Packed.Instrument (InputArg(Modulation))
 import Synthesizer.LLVM.Server.ALSA (makeNote)
-import Synthesizer.LLVM.Server.CommonPacked
-          (Vector, vectorSize)
-import Synthesizer.LLVM.Server.Common hiding
-          (Instrument)
+import Synthesizer.LLVM.Server.CommonPacked (Vector, vectorSize)
+import Synthesizer.LLVM.Server.Common hiding (Instrument)
 
 import qualified Sound.ALSA.Sequencer.Event as Event
 import qualified Synthesizer.MIDI.PiecewiseConstant as PC
 import qualified Synthesizer.MIDI.Generic as Gen
 
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector.Plain as Serial
 
 import qualified Synthesizer.ALSA.Storable.Play as Play
 import Synthesizer.MIDI.Storable (Instrument, chunkSizesFromLazyTime)
 
 import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Render as Render
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
-import Synthesizer.LLVM.CausalParameterized.Process (($*))
+import Synthesizer.LLVM.Causal.Process (($*))
 
 import qualified Synthesizer.Storable.Cut         as CutSt
 import qualified Synthesizer.Storable.Signal      as SigSt
@@ -36,7 +36,7 @@
 import qualified Data.EventList.Relative.BodyTime  as EventListBT
 
 import Control.Arrow ((<<<), arr)
-import Control.Applicative (pure, liftA, liftA2)
+import Control.Applicative (pure, liftA, liftA2, (<$>))
 import Control.Monad.Trans.State (evalState)
 
 import qualified Numeric.NonNegative.Wrapper as NonNegW
@@ -212,11 +212,8 @@
    liftA
       (\osc smp _fm _vel _freq _dur ->
          osc chunkSize (Sample.body smp))
-      (SigP.runChunky
-         (let smp = arr id
-          in  fmap (\x -> Stereo.cons x x) $
-              SigPS.pack $
-              SigP.fromStorableVectorLazy smp))
+      (Render.run $ \smp ->
+         fmap (\x -> Stereo.consMultiValue x x) $ SigPS.pack smp)
 
 sampledSoundTest1 ::
    IO (Sample.T ->
@@ -226,15 +223,13 @@
    liftA
       (\osc smp _fm _vel _freq _dur ->
          osc chunkSize (Sample.body smp))
-      (SigP.runChunky
-         (let smp = arr id
-          in  CausalP.stereoFromMono
-                 (CausalPS.pack
-                    (CausalP.frequencyModulationLinear
-                       (SigP.fromStorableVectorLazy smp)))
+      (Render.run $ \smp ->
+         Stereo.multiValue <$>
+         Causal.stereoFromMono
+                  (CausalPS.pack (Causal.frequencyModulationLinear smp))
                $* liftA2 Stereo.cons
                      (SigPS.constant 0.999)
-                     (SigPS.constant 1.001)))
+                     (SigPS.constant 1.001))
 --               $* (SigPS.constant $# Stereo.cons 0.999 1.001)))
 
 sampledSoundTest2 ::
@@ -250,20 +245,18 @@
                 SigSt.drop (Sample.start pos) $
                 Sample.body smp
          in  SVP.take (chunkSizesFromLazyTime dur) $
-             osc chunkSize
-                (sampleRate, (body, (fm, freq * Sample.period pos))))
-      (SigP.runChunky
-         (let smp = signal fst
-              fm = Instr.modulation snd
-          in  (CausalP.stereoFromMono
-                  (CausalPS.pack
-                     (CausalP.frequencyModulationLinear
-                        (SigP.fromStorableVectorLazy smp)))
+             osc chunkSize sampleRate body (fm, freq * Sample.period pos))
+      (Render.run $
+       wrapped $ \(Signal smp) (Modulation fm) ->
+       constant frequency 3 $ \speed _sr ->
+         Stereo.multiValue <$>
+         ((Causal.stereoFromMono
+                  (CausalPS.pack (Causal.frequencyModulationLinear smp))
                <<<
                liftA2 Stereo.cons
                   (CausalPS.amplify 0.999)
                   (CausalPS.amplify 1.001))
-                 $* Instr.frequencyFromBendModulation (frequencyConst 3) fm))
+                 $* Instr.frequencyFromBendModulation speed fm))
 
 sampledSoundTest3SpaceLeak ::
    IO (Sample.T ->
@@ -278,30 +271,28 @@
          Without (periodic) frequency modulation
          we could just split the piecewise constant control curve @fm@.
          -}
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (SigSt.repeat chunkSize
+                SigSt.repeat chunkSize
                    (Serial.replicate (freq*Sample.period pos/sampleRatePlain))
-                      :: SigSt.T Vector)
              pos = Sample.positions smp
              amp = 2 * amplitudeFromVelocity vel
              (attack, sustain, release) = Sample.parts smp
-         in  osc
-                (amp,
-                 attack `SigSt.append`
-                 SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))
-                sustainFM
-             `SigSt.append`
-             osc (amp,release) releaseFM)
-      (CausalP.runStorableChunky
-         (let smp = arr snd
-              amp = arr fst
-          in  CausalPS.amplifyStereo amp
+         in pioApply
+              (osc amp
+                (attack `SigSt.append`
+                 SVL.cycle (SigSt.take (Sample.loopLength pos) sustain)))
+              sustainFM
+            `SigSt.append`
+            pioApply (osc amp release) releaseFM)
+      (CausalRender.run $ \amp smp ->
+         Stereo.multiValue <$>
+         (CausalPS.amplifyStereo amp
               <<<
-              CausalP.stereoFromMono
+              Causal.stereoFromMono
                  (CausalPS.pack
-                    (CausalP.frequencyModulationLinear
-                       (SigP.fromStorableVectorLazy smp)))
+                    (Causal.frequencyModulationLinear smp))
               <<<
               liftA2 Stereo.cons
                  (CausalPS.amplify 0.999)
@@ -320,18 +311,20 @@
          Without (periodic) frequency modulation
          we could just split the piecewise constant control curve @fm@.
          -}
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (freqMod
-                   (chunkSizesFromLazyTime (PC.duration fm))
-                   (sampleRate, (fm, freq*Sample.period pos)) :: SigSt.T Vector)
+                pioApplyToLazyTime
+                   (freqMod sampleRate (fm, freq*Sample.period pos))
+                   (PC.duration fm)
              pos = Sample.positions smp
          in  SigSt.map
                 (\x -> Stereo.cons x x)
                 (sustainFM `SigSt.append` releaseFM))
-      (SigP.runChunkyPattern
-         (Instr.frequencyFromBendModulation
-            (frequencyConst 3) (Instr.modulation id)))
+      (CausalRender.run $
+       wrapped $ \(Modulation fm) ->
+       constant frequency 3 $ \speed _sr ->
+       Causal.fromSignal $ Instr.frequencyFromBendModulation speed fm)
 
 sampledSoundTest5LargeSpaceLeak ::
    IO (Sample.T ->
@@ -346,26 +339,27 @@
          Without (periodic) frequency modulation
          we could just split the piecewise constant control curve @fm@.
          -}
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (freqMod
-                   (chunkSizesFromLazyTime (PC.duration fm))
-                   (sampleRate, (fm, freq*Sample.period pos)) :: SigSt.T Vector)
+                pioApplyToLazyTime
+                   (freqMod sampleRate (fm, freq*Sample.period pos))
+                   (PC.duration fm)
              pos = Sample.positions smp
              amp = 2 * amplitudeFromVelocity vel
              (attack, sustain, release) = Sample.parts smp
-         in  osc
-                (amp,
-                 attack `SigSt.append`
-                 SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))
-                sustainFM
-             `SigSt.append`
-             osc (amp,release) releaseFM)
-      (CausalP.runStorableChunky
-         (arr (\x -> Stereo.cons x x)))
-      (SigP.runChunkyPattern
-         (Instr.frequencyFromBendModulation
-            (frequencyConst 3) (Instr.modulation id)))
+         in pioApply
+              (osc amp
+                 (attack `SigSt.append`
+                  SVL.cycle (SigSt.take (Sample.loopLength pos) sustain)))
+              sustainFM
+            `SigSt.append`
+            pioApply (osc amp release) releaseFM)
+      (CausalRender.run $ \ _amp _smp -> arr (\x -> Stereo.consMultiValue x x))
+      (CausalRender.run $
+       wrapped $ \(Modulation fm) ->
+       constant frequency 3 $ \speed _sr ->
+       Causal.fromSignal $ Instr.frequencyFromBendModulation speed fm)
 
 
 sampledSoundSmallSpaceLeak4 ::
@@ -375,17 +369,16 @@
 sampledSoundSmallSpaceLeak4 =
    liftA
       (\osc smp _fm _vel freq dur ->
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (SigSt.repeat chunkSize
+                SigSt.repeat chunkSize
                    (Serial.replicate (freq*Sample.period pos/sampleRatePlain))
-                      :: SigSt.T Vector)
              pos = Sample.positions smp
-         in  osc () sustainFM
+         in  pioApply osc sustainFM
              `SigSt.append`
              SigSt.map (\x -> Stereo.cons x x) releaseFM)
-      (CausalP.runStorableChunky
-         (arr (\x -> Stereo.cons x x)))
+      (CausalRender.run $ arr (\x -> Stereo.consMultiValue x x))
 
 sampledSoundSmallSpaceLeak4a ::
    IO (Sample.T ->
@@ -395,15 +388,13 @@
    liftA
       (\osc smp _fm _vel freq dur ->
          case SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (SigSt.repeat chunkSize
-                   (Serial.replicate (freq*Sample.period (Sample.positions smp) / sampleRatePlain))
-                      :: SigSt.T Vector) of
+                SigSt.repeat chunkSize
+                   (Serial.replicate (freq*Sample.period (Sample.positions smp) / sampleRatePlain)) of
             (sustainFM, releaseFM) ->
-               osc () sustainFM
+               pioApply osc (sustainFM :: SigSt.T Vector)
                `SigSt.append`
                SigSt.map (\x -> Stereo.cons x x) releaseFM)
-      (CausalP.runStorableChunky
-         (arr (\x -> Stereo.cons x x)))
+      (CausalRender.run $ arr (\x -> Stereo.consMultiValue x x))
 
 sampledSoundNoSmallSpaceLeak3 ::
    IO (Sample.T ->
@@ -412,11 +403,11 @@
 sampledSoundNoSmallSpaceLeak3 =
    pure
       (\smp _fm _vel freq dur ->
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (SigSt.repeat chunkSize
+                SigSt.repeat chunkSize
                    (Serial.replicate (freq*Sample.period pos/sampleRatePlain))
-                      :: SigSt.T Vector)
              pos = Sample.positions smp
          in  SigSt.map (\x -> Stereo.cons x x) sustainFM
              `SigSt.append`
@@ -433,18 +424,17 @@
 sampledSoundNoSmallSpaceLeak2 =
    liftA
       (\osc smp _fm _vel freq dur ->
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (SigSt.repeat chunkSize
+                SigSt.repeat chunkSize
                    (Serial.replicate (freq*Sample.period pos/sampleRatePlain))
-                      :: SigSt.T Vector)
              pos = Sample.positions smp
-         in  osc ()
+         in  pioApply osc
                 (amplifySVL sustainFM
                  `SigSt.append`
                  amplifySVL releaseFM))
-      (CausalP.runStorableChunky
-         (arr (\x -> Stereo.cons x x)))
+      (CausalRender.run $ arr (\x -> Stereo.consMultiValue x x))
 
 sampledSoundSmallSpaceLeak1 ::
    IO (Sample.T ->
@@ -453,17 +443,16 @@
 sampledSoundSmallSpaceLeak1 =
    liftA
       (\osc smp _fm _vel freq dur ->
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (SigSt.repeat chunkSize
+                SigSt.repeat chunkSize
                    (Serial.replicate (freq*Sample.period pos/sampleRatePlain))
-                      :: SigSt.T Vector)
              pos = Sample.positions smp
-         in  osc () sustainFM
+         in  pioApply osc sustainFM
              `SigSt.append`
-             osc () releaseFM)
-      (CausalP.runStorableChunky
-         (arr (\x -> Stereo.cons x x)))
+             pioApply osc releaseFM)
+      (CausalRender.run $ arr (\x -> Stereo.consMultiValue x x))
 
 sampledSoundSmallSpaceLeak0 ::
    IO (Sample.T ->
@@ -478,23 +467,22 @@
          Without (periodic) frequency modulation
          we could just split the piecewise constant control curve @fm@.
          -}
-         let (sustainFM, releaseFM) =
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
                 SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (SigSt.repeat chunkSize
+                SigSt.repeat chunkSize
                    (Serial.replicate (freq*Sample.period pos/sampleRatePlain))
-                      :: SigSt.T Vector)
              pos = Sample.positions smp
              amp = 2 * amplitudeFromVelocity vel
              (attack, sustain, release) = Sample.parts smp
-         in  osc
-                (amp,
-                 attack `SigSt.append`
-                 SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))
+         in  pioApply
+                (osc amp
+                   (attack `SigSt.append`
+                    SVL.cycle (SigSt.take (Sample.loopLength pos) sustain)))
                 sustainFM
              `SigSt.append`
-             osc (amp,release) releaseFM)
-      (CausalP.runStorableChunky
-         (arr (\x -> Stereo.cons x x)))
+             pioApply (osc amp release) releaseFM)
+      (CausalRender.run $ \ _amp _smp -> arr (\x -> Stereo.consMultiValue x x))
 
 makeSample :: Int -> Sample.T
 makeSample size =
@@ -571,10 +559,10 @@
    let stereoPlain = SigSt.map (\x -> Stereo.cons x x)
    SVL.writeFile "test.f32" $
       let dur = NonNegChunky.fromChunks $ repeat $ SVL.chunkSize 10
+          sustainFM, releaseFM :: SigSt.T Vector
           !(sustainFM, releaseFM) =
              SVP.splitAt dur $
-             (SigSt.repeat chunkSize (Serial.replicate 1)
-                 :: SigSt.T Vector)
+             SigSt.repeat chunkSize (Serial.replicate 1)
       in  case 3::Int of
              -- no leak
              0 -> stereoLLVM  $ sustainFM `SigSt.append` releaseFM
@@ -633,8 +621,7 @@
    SVL.writeFile "test.f32" $
       arrange vectorChunkSize $
       evalState
-         (let evs =
-                 EventListBT.cons (BM.Cons 0.01 0.001) 10 evs
+         (let evs = EventListBT.cons (BM.Cons 0.01 0.001) 10 evs
           in  Gen.sequenceCore
                  Default.channel Gen.errorNoProgram
                  (Gen.Modulator () return
@@ -646,8 +633,7 @@
 sequenceFM1 = do
    arrange <- SigStL.makeArranger
    sound <- Instr.softStringFM $/
-      let evs =
-             EventListBT.cons (BM.Cons 0.01 0.001) 10 evs
+      let evs = EventListBT.cons (BM.Cons 0.01 0.001) 10 evs
       in  evs
 --   sound <- Instr.softStringReleaseEnvelope
    SVL.writeFile "test.f32" $
diff --git a/alsa/Synthesizer/LLVM/Server/Scalar/Run.hs b/alsa/Synthesizer/LLVM/Server/Scalar/Run.hs
--- a/alsa/Synthesizer/LLVM/Server/Scalar/Run.hs
+++ b/alsa/Synthesizer/LLVM/Server/Scalar/Run.hs
@@ -3,20 +3,23 @@
 import qualified Synthesizer.LLVM.Server.Scalar.Instrument as Instr
 import qualified Synthesizer.LLVM.Server.Option as Option
 import Synthesizer.LLVM.Server.ALSA (Output, play, startMessage)
-import Synthesizer.LLVM.Server.Common
+import Synthesizer.LLVM.Server.CausalPacked.Common (transposeModulation)
+import Synthesizer.LLVM.Server.Common hiding (transposeModulation)
 
 import qualified Sound.ALSA.Sequencer.Event as Event
 import qualified Data.EventList.Relative.TimeBody  as EventList
 
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
 import qualified Synthesizer.LLVM.MIDI as MIDIL
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Synthesizer.LLVM.Wave as WaveL
-import Synthesizer.LLVM.Causal.Process (($<#), ($*))
+import Synthesizer.LLVM.Causal.Process (($<), ($*))
 
-import qualified Synthesizer.Storable.Signal      as SigSt
+import qualified Synthesizer.Storable.Signal as SigSt
 
 import qualified Synthesizer.ALSA.EventList as Ev
 
@@ -25,8 +28,9 @@
 
 import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
 
-import Control.Arrow ((<<<), arr)
+import Control.Arrow ((^<<), (<<^))
 import Control.Monad.Trans.State (evalState)
+import Control.Applicative ((<$>))
 
 import Control.Exception (bracket)
 
@@ -57,35 +61,31 @@
 
 
 
-freq :: Option.SampleRate Real -> Real -> Real
-freq (Option.SampleRate sampleRate) f =
-   f / sampleRate
-
-
 pitchBend :: IO ()
 pitchBend = do
    opt <- Option.get
    osc <-
-      SigP.runChunky
-         ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))
-             $* piecewiseConstant (arr id))
+      Render.run $ \fm ->
+         Causal.osci WaveL.triangle $< zero $* piecewiseConstant fm
    withMIDIEvents opt play $ \chunkSize sampleRate ->
       (id :: SigSt.T Real -> SigSt.T Real) .
       osc chunkSize .
-      evalState (PC.pitchBend (Option.channel opt) 2 (freq sampleRate 880))
+      evalState (PC.pitchBend (Option.channel opt) 2 (frequency sampleRate 880))
 
 
 frequencyModulation :: IO ()
 frequencyModulation = do
    opt <- Option.get
    osc <-
-      SigP.runChunky
-         (((CausalP.osciSimple WaveL.triangle $<# (zero::Real))
-              <<< (MIDIL.frequencyFromBendModulation (frequencyConst (10::Real))))
-           $* piecewiseConstant (arr (\(sr,ctrl) -> transposeModulation sr 880 ctrl)))
+      Render.run $
+      constant frequency 10 $ \speed _sr fm ->
+         Causal.osci WaveL.triangle
+            $< zero
+            $* (MIDIL.frequencyFromBendModulation speed
+                  $* piecewiseConstant (fmap BM.unMultiValue <$> fm))
    withMIDIEvents opt play $ \chunkSize sampleRate ->
       (id :: SigSt.T Real -> SigSt.T Real) .
-      osc chunkSize . (,) sampleRate .
+      osc chunkSize sampleRate . transposeModulation sampleRate 880 .
       evalState (PC.bendWheelPressure (Option.channel opt) 2 0.04 (0.03::Real))
 
 
@@ -100,10 +100,10 @@
       (Instr.pingReleaseEnvelope $/ 0.4 $/ 0.1)
 -}
    sound <- Instr.pingRelease $/ 0.4 $/ 0.1
-   amp <- CausalP.runStorableChunky (CausalP.amplify (arr id))
+   amp <- CausalRender.run Causal.amplify
    arrange <- SigStL.makeArranger
    withMIDIEvents opt play $ \chunkSize sampleRate ->
-      (amp :: Real -> SigSt.T Real -> SigSt.T Real) 0.2 .
+      pioApply (amp (0.2 :: Real)) .
       arrange chunkSize .
       evalState
          (Gen.sequence
@@ -114,10 +114,12 @@
 keyboardStereo = do
    opt <- Option.get
    sound <- Instr.pingStereoRelease $/ 0.4 $/ 0.1
-   amp <- CausalP.runStorableChunky (CausalP.amplifyStereo (arr id))
+   amp <-
+      CausalRender.run $ \vol ->
+         Stereo.multiValue ^<< Causal.amplifyStereo vol <<^ Stereo.unMultiValue
    arrange <- SigStL.makeArranger
    withMIDIEvents opt play $ \chunkSize sampleRate ->
-      (amp :: Real -> SigSt.T (Stereo.T Real) -> SigSt.T (Stereo.T Real)) 0.2 .
+      pioApply (amp (0.2 :: Real)) .
       arrange chunkSize .
       evalState
          (Gen.sequence
diff --git a/alsa/Synthesizer/LLVM/Server/Scalar/Test.hs b/alsa/Synthesizer/LLVM/Server/Scalar/Test.hs
--- a/alsa/Synthesizer/LLVM/Server/Scalar/Test.hs
+++ b/alsa/Synthesizer/LLVM/Server/Scalar/Test.hs
@@ -13,10 +13,10 @@
 import qualified Synthesizer.MIDI.PiecewiseConstant as PC
 import qualified Synthesizer.MIDI.Generic as Gen
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
 import qualified Synthesizer.LLVM.Wave as WaveL
-import Synthesizer.LLVM.Causal.Process (($<#), ($*))
+import Synthesizer.LLVM.Causal.Process (($<), ($*))
 
 import qualified Synthesizer.Storable.Cut         as CutSt
 import qualified Synthesizer.Storable.Signal      as SigSt
@@ -24,7 +24,6 @@
 
 import qualified Data.EventList.Relative.TimeBody  as EventList
 
-import Control.Arrow (arr)
 import Control.Monad.Trans.State (evalState)
 
 import NumericPrelude.Numeric (zero)
@@ -34,9 +33,6 @@
 chunkSize :: SVL.ChunkSize
 chunkSize = Play.defaultChunkSize
 
-sampleRatePlain :: Real
-sampleRatePlain = case Default.sampleRate of SampleRate r -> r
-
 sampleRate :: SampleRate Real
 sampleRate = Default.sampleRate
 
@@ -44,13 +40,12 @@
 pitchBend0 :: IO ()
 pitchBend0 = do
    osc <-
-      SigP.runChunky
-         ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))
-             $* piecewiseConstant (arr id))
+      Render.run $ \fm ->
+         Causal.osci WaveL.triangle $< zero $* piecewiseConstant fm
    SVL.writeFile "test.f32" $
       (id :: SigSt.T Real -> SigSt.T Real) .
       osc chunkSize .
-      evalState (PC.pitchBend Default.channel 2 (880/sampleRatePlain)) $
+      evalState (PC.pitchBend Default.channel 2 (frequency sampleRate 880)) $
       let evs = EventList.cons 100 [] evs
       in  EventList.cons 0 ([]::[Event.T]) evs
 
@@ -58,13 +53,12 @@
 pitchBend1 = do
    opt <- Option.get
    osc <-
-      SigP.runChunky
-         ((CausalP.osciSimple WaveL.triangle $<# (zero::Real))
-             $* piecewiseConstant (arr id))
+      Render.run $ \fm ->
+         Causal.osci WaveL.triangle $< zero $* piecewiseConstant fm
    withMIDIEvents opt (record "test.f32") $ \ _size _rate ->
       (id :: SigSt.T Real -> SigSt.T Real) .
       osc chunkSize .
-      evalState (PC.pitchBend Default.channel 2 (880/sampleRatePlain))
+      evalState (PC.pitchBend Default.channel 2 (frequency sampleRate 880))
 
 pitchBend2 :: IO ()
 pitchBend2 = do
diff --git a/example/Synthesizer/LLVM/ExampleUtility.hs b/example/Synthesizer/LLVM/ExampleUtility.hs
new file mode 100644
--- /dev/null
+++ b/example/Synthesizer/LLVM/ExampleUtility.hs
@@ -0,0 +1,29 @@
+module Synthesizer.LLVM.ExampleUtility where
+
+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+
+import Type.Data.Num.Decimal (D4, D16)
+
+import Data.Word (Word32)
+
+
+type Id a = a -> a
+
+asMono :: Id (vector Float)
+asMono = id
+
+asStereo :: Id (vector (Stereo.T Float))
+asStereo = id
+
+asMonoPacked :: Id (vector (Serial.T D4 Float))
+asMonoPacked = id
+
+asMonoPacked16 :: Id (vector (Serial.T D16 Float))
+asMonoPacked16 = id
+
+asWord32 :: Id (vector Word32)
+asWord32 = id
+
+asWord32Packed :: Id (vector (Serial.T D4 Word32))
+asWord32Packed = id
diff --git a/example/Synthesizer/LLVM/LAC2011.hs b/example/Synthesizer/LLVM/LAC2011.hs
--- a/example/Synthesizer/LLVM/LAC2011.hs
+++ b/example/Synthesizer/LLVM/LAC2011.hs
@@ -2,6 +2,8 @@
 {-# OPTIONS_GHC -fno-warn-unused-imports #-}
 module Synthesizer.LLVM.LAC2011 where
 
+import Synthesizer.LLVM.ExampleUtility
+
 import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass
 import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
 import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth
@@ -11,34 +13,32 @@
 import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P
 import qualified Synthesizer.LLVM.Filter.Moog as Moog
 import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
-import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP
-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessValue as CausalPV
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.ProcessValue as CausalV
+import qualified Synthesizer.LLVM.Causal.Controlled as Ctrl
 import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Simple.Signal as Gen
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.SignalPacked as GenP
+import qualified Synthesizer.LLVM.Generator.Signal as Gen
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
 import qualified Synthesizer.LLVM.Frame as Frame
 import qualified Synthesizer.LLVM.Wave as Wave
-import qualified Synthesizer.LLVM.Parameter as Param
 
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
 import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Tuple as Tuple
-import LLVM.Core (Value, value, valueOf, Vector, constVector, constOf)
-import LLVM.Util.Arithmetic () -- Floating instance for TValue
+
 import qualified LLVM.Core as LLVM
-import Type.Data.Num.Decimal (D4, D8, D16, d0, d1, d2, d3, d4, d5, d6, d7, d8)
+
 import qualified Type.Data.Num.Decimal as TypeNum
+import Type.Data.Num.Decimal (D4, D8, D16, d0, d1, d2, d3, d4, d5, d6, d7, d8)
 
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as GenPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as GenP
 import Synthesizer.LLVM.Causal.Process (($<), ($*), ($*#))
-import Synthesizer.LLVM.Parameter (($#))
 
 import qualified Synthesizer.Plain.Filter.Recursive as FiltR
 import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core
@@ -70,7 +70,6 @@
 -- import qualified Sound.ALSA.PCM as ALSA
 -- import qualified Synthesizer.ALSA.Storable.Play as Play
 
-import Data.Word (Word32)
 import Data.List (genericLength)
 import System.Random (randomRs, mkStdGen)
 
@@ -85,52 +84,23 @@
 import qualified NumericPrelude.Base as P
 
 
-asMono :: vector Float -> vector Float
-asMono = id
-
-asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)
-asStereo = id
-
-asMonoPacked :: vector (LLVM.Vector D4 Float) -> vector (LLVM.Vector D4 Float)
-asMonoPacked = id
-
-asMonoPacked16 :: vector (LLVM.Vector D16 Float) -> vector (LLVM.Vector D16 Float)
-asMonoPacked16 = id
-
-asWord32 :: vector Word32 -> vector Word32
-asWord32 = id
-
-asWord32Packed :: vector (LLVM.Vector D4 Word32) -> vector (LLVM.Vector D4 Word32)
-asWord32Packed = id
-
-
-playStereo :: Gen.T (Stereo.T (Value Float)) -> IO ()
-playStereo =
-   playStereoStream .
-   Gen.renderChunky (SVL.chunkSize 100000)
+playStereo :: Gen.T (Stereo.T (MultiValue.T Float)) -> IO ()
+playStereo sig =
+   playStereoStream . ($ SVL.chunkSize 100000) =<<
+   Render.run (fmap Stereo.multiValue sig)
 
 playStereoStream :: SVL.Vector (Stereo.T Float) -> IO ()
 playStereoStream = playStreamSox
 
-playMono :: Gen.T (Value Float) -> IO ()
-playMono =
-   playMonoStream .
-   Gen.renderChunky (SVL.chunkSize 100000)
-
-playMonoParam :: GenP.T () (Value Float) -> IO ()
-playMonoParam =
-   playMonoStream .
-   ($ ()) .
-   ($ SVL.chunkSize 100000) <=<
-   GenP.runChunky
+playMono :: Gen.MV Float -> IO ()
+playMono sig  =  playMonoStream . ($ SVL.chunkSize 100000) =<< Render.run sig
 
-playMonoPacked :: GenP.T () (Serial.Value D4 Float) -> IO ()
+playMonoPacked :: Gen.T (MultiValue.T (Serial.T D4 Float)) -> IO ()
 playMonoPacked =
    playMonoStream .
    SigStL.unpack .
-   ($ ()) .
    ($ SVL.chunkSize 100000) <=<
-   GenP.runChunky
+   Render.run
 
 playMonoStream :: SVL.Vector Float -> IO ()
 playMonoStream = playStreamSox
@@ -139,7 +109,7 @@
 {-
 play ::
    (C.MakeValueTuple y, Tuple.ValueOf y ~ a, Memory.C a struct) =>
-   Gen.T a -> IO ()
+   Gen.MV a -> IO ()
 play =
    playStreamSox .
    Gen.renderChunky (SVL.chunkSize 100000)
@@ -167,26 +137,12 @@
 intSecond :: Ring.C a => Float -> a
 intSecond t = fromInteger $ round $ t * sampleRate
 
-secondP :: Param.T p Float -> Param.T p Float
-secondP t = t * sampleRate
-
-hertzP :: Param.T p Float -> Param.T p Float
-hertzP f = f / sampleRate
-
 second :: Field.C a => a -> a
 second t = t * sampleRate
 
 hertz :: Field.C a => a -> a
 hertz f = f / sampleRate
 
-{-
-second :: Float -> Param.T p Float
-second t = return (t * sampleRate)
-
-hertz :: Float -> Param.T p Float
-hertz f = return (f / sampleRate)
--}
-
 sine :: IO ()
 sine =
    playMono (0.99 * Gen.osci Wave.sine 0 (hertz 440))
@@ -209,18 +165,11 @@
    playStereo (traverse (Gen.osci Wave.triangle 0 . hertz) (Stereo.cons 439 441))
 
 
-fst :: Arrow arrow => arrow (a,b) a
-fst = arr P.fst
-
-snd :: Arrow arrow => arrow (a,b) b
-snd = arr P.snd
-
-
 pingParam :: IO (Float -> SVL.Vector Float)
 pingParam =
    fmap ($ SVL.chunkSize 1024) $
-   GenP.runChunky $
-   GenP.exponential2 (second 0.3) 1 * GenP.osciSimple Wave.triangle 0 id
+   Render.run $ \freq ->
+   Gen.exponential2 (second 0.3) 1 * Gen.osci Wave.triangle 0 freq
 
 playPingParam :: IO ()
 playPingParam = do
@@ -240,8 +189,8 @@
 pingParam2 :: IO ((Float, Float) -> SVL.Vector Float)
 pingParam2 =
    fmap ($ SVL.chunkSize 1024) $
-   GenP.runChunky $
-   GenP.exponential2 (second 0.3) fst * GenP.osciSimple Wave.triangle 0 snd
+   Render.run $ \(amp,freq) ->
+   Gen.exponential2 (second 0.3) amp * Gen.osci Wave.triangle 0 freq
 
 playMelody2 :: IO ()
 playMelody2 = do
@@ -249,86 +198,57 @@
    playMonoStream $ SVL.concat $ map (SVL.take (intSecond 0.2) . png) $ zip (map sin $ [0,0.1..]) (cycle $ map hertz [440, 550, 660, 880])
 
 
-retard :: GenP.T p (Value Float) -> GenP.T p (Value Float)
+retard :: Gen.MV Float -> Gen.MV Float
 retard xs =
-   CausalP.frequencyModulationLinear xs .
-   CausalV.map Field.recip $*
-   GenP.rampCore (1 / secondP 10) 1
+   Causal.frequencyModulationLinear xs .
+   Causal.map Field.recip $*
+   (1 + Gen.rampInf (second 10))
 
 playRetarded :: IO ()
 playRetarded = do
    mel <- melody
-   playMonoParam $ retard $ GenP.fromStorableVectorLazy $ pure $ mel
+   ret <- Render.run retard
+   playMonoStream $ ret (SVL.chunkSize 10000) mel
 
 
 
-pingGen :: GenP.T p (Value Float)
+pingGen :: Gen.MV Float
 pingGen =
-   GenP.exponential2 (second 0.5) 0.7 *
-   GenP.osciSimple Wave.triangle 0 (hertzP 440)
-
-delayp :: Param.T p Int -> CausalP.T p (Value Float) (Value Float)
-delayp = CausalP.delayZero
+   Gen.exponential2 (second 0.5) 0.7 *
+   Gen.osci Wave.triangle 0 (hertz 440)
 
 delay :: IO ()
 delay =
-   playMonoParam $
-      pingGen + 0.7 * (delayp (intSecond 0.5) $* pingGen)
+   playMono $
+      pingGen + 0.7 * (Causal.delay 0 (intSecond 0.5) $* pingGen)
 
 delayArrow :: IO ()
 delayArrow =
-   playMonoParam
-      ((id + 0.7 * delayp (intSecond 0.5)) $* pingGen)
+   playMono
+      ((id + 0.7 * Causal.delay 0 (intSecond 0.5)) $* pingGen)
 
 comb :: IO ()
 comb =
-   playMonoParam $
-      (CausalP.loopZero
-          (id  &&&  0.7 * delayp (intSecond 0.5)
-             <<< CausalP.mix) $*
+   playMono $
+      (Causal.loopZero
+          (id  &&&  0.7 * Causal.delay 0 (intSecond 0.5)
+             <<< Causal.mix) $*
        pingGen)
 
 
-lfoSine ::
-   Param.T p Float ->
-   GenP.T p (Moog.Parameter D8 (Value Float))
+lfoSine :: Exp Float -> Gen.T (Moog.Parameter D8 (MultiValue.T Float))
 lfoSine reduct =
-   Causal.map (Moog.parameter d8 (valueOf (30::Float))) .
-   CausalP.mapExponential 2 (hertz 700) $*
-   GenP.osciSimple Wave.sine 0 (reduct * hertz 0.1)
+   Causal.map (Moog.parameter d8 30 . (hertz 700 *) . (2**))
+   $*
+   Gen.osci Wave.sine 0 (reduct * hertz 0.1)
 
 filterSweep :: IO ()
 filterSweep =
-   playMonoParam $
-      (0.2 * CtrlP.processCtrlRate 128 lfoSine
-       $* GenP.noise 0 0.3)
+   playMono $
+      (Ctrl.processCtrlRate 128 lfoSine $* Gen.noise 0 (recip $ hertz 3.5e6))
 
 
 pingPacked :: IO ()
 pingPacked =
-   playMonoPacked (GenPS.exponential2 (second 1) 1 * GenPS.osciSimple Wave.triangle 0 (hertz 440))
-
-
-
-{-
-Module can be loaded into GHCi only when synthesizer-llvm was installed with
-$ cabal install --enable-shared
-
-In contrast to that, you have to install with
-$ cabal install -fbuildTests -fbuildExamples --enable-shared --disable-library-profiling --ghc-option=-dynamic
-for build the executables.
-But then GHCi complains:
-
-$ ghci
-GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
-Loading package ghc-prim ... linking ... done.
-Loading package integer-gmp ... linking ... done.
-Loading package base ... linking ... done.
-Loading package ffi-1.0 ... linking ... done.
-[1 of 1] Compiling Main             ( src/Synthesizer/LLVM/Test.hs, interpreted )
-
-src/Synthesizer/LLVM/Test.hs:4:0:
-    Bad interface file: /home/thielema/.cabal/lib/synthesizer-llvm-0.3/ghc-6.12.3/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hi
-        mismatched interface file ways (wanted "", got "dyn")
-Failed, modules loaded: none.
--}
+   playMonoPacked $
+      GenP.exponential2 (second 1) 1 * GenP.osci Wave.triangle 0 (hertz 440)
diff --git a/example/Synthesizer/LLVM/LNdW2011.hs b/example/Synthesizer/LLVM/LNdW2011.hs
--- a/example/Synthesizer/LLVM/LNdW2011.hs
+++ b/example/Synthesizer/LLVM/LNdW2011.hs
@@ -1,17 +1,27 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# OPTIONS_GHC -fno-warn-unused-imports #-}
 module Synthesizer.LLVM.LNdW2011 where
 
+import Synthesizer.LLVM.ExampleUtility
+
+import qualified Synthesizer.LLVM.Causal.Render as Render
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalP
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as SigRender
+import qualified Synthesizer.LLVM.Generator.SignalPacked as GenP
+import qualified Synthesizer.LLVM.Generator.Signal as Gen
+
 import qualified Synthesizer.LLVM.Plug.Input as PIn
 import qualified Synthesizer.LLVM.Plug.Output as POut
 import qualified Synthesizer.MIDI.PiecewiseConstant.ControllerSet as PCS
 import qualified Synthesizer.MIDI.EventList as Ev
 import qualified Synthesizer.MIDI.CausalIO.ControllerSelection as MCS
 import qualified Synthesizer.MIDI.CausalIO.Process as PMIDI
+import qualified Synthesizer.MIDI.Value as MV
 import qualified Synthesizer.ALSA.CausalIO.Process as PALSA
 import qualified Synthesizer.CausalIO.Process as PIO
-import qualified Synthesizer.MIDI.Value as MV
 import qualified Synthesizer.Zip as Zip
 import Synthesizer.ALSA.EventList (ClientName(ClientName))
 
@@ -28,34 +38,28 @@
 import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P
 import qualified Synthesizer.LLVM.Filter.Moog as Moog
 import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
-import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP
-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Simple.Signal as Gen
-import qualified Synthesizer.LLVM.Simple.Value as Value
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
 import qualified Synthesizer.LLVM.Frame as Frame
 import qualified Synthesizer.LLVM.Wave as Wave
-import qualified Synthesizer.LLVM.Parameter as Param
 
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Core as LLVM
 import LLVM.Core (Value, value, valueOf, constVector, constOf)
 import LLVM.Util.Arithmetic () -- Floating instance for TValue
-import qualified LLVM.Core as LLVM
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal (D4, D8, D16, d0, d1, d2, d3, d4, d5, d6, d7, d8)
 
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as GenPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as GenP
-import Synthesizer.LLVM.Causal.Process (($<), ($*), ($*#), ($<#))
-import Synthesizer.LLVM.Parameter (($#))
+import qualified Synthesizer.Causal.Class as CausalClass
+import Synthesizer.Causal.Class (($<), ($*))
 
 import qualified Synthesizer.Plain.Filter.Recursive as FiltR
 import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core
@@ -65,17 +69,17 @@
 
 import qualified Control.Monad.Trans.State as State
 import qualified Control.Arrow as Arr
-import Control.Arrow (Arrow, arr, (&&&), (^<<), (^>>))
+import Control.Arrow (Arrow, arr, (&&&), (***), (^<<), (^>>), (>>^))
 import Control.Category ((<<<), (.), id, (>>>))
 import Control.Monad (liftM2, (<=<))
-import Control.Applicative (liftA2, pure)
+import Control.Applicative (liftA2, pure, (<$>))
 import Control.Functor.HT (void)
 import Data.Tuple.HT (mapPair)
 import Data.Traversable (traverse)
 
-import Foreign.Storable (Storable)
 import qualified Data.StorableVector.Lazy as SVL
 import qualified Data.StorableVector as SV
+import Foreign.Storable (Storable)
 
 import qualified Data.EventList.Relative.TimeBody  as EventList
 import qualified Data.EventList.Relative.BodyTime  as EventListBT
@@ -95,13 +99,13 @@
 import qualified Sound.ALSA.PCM as ALSA
 import qualified Synthesizer.ALSA.Storable.Play as Play
 
-import Data.Word (Word32)
 import Data.List (genericLength)
 import System.Random (randomRs, mkStdGen)
 
 import qualified System.IO as IO
 
 import qualified Algebra.NormedSpace.Euclidean as NormedEuc
+import qualified Algebra.Algebraic as Algebraic
 import qualified Algebra.Field as Field
 import qualified Algebra.Ring as Ring
 import qualified Algebra.Additive as Additive
@@ -112,52 +116,24 @@
 import qualified NumericPrelude.Base as P
 
 
-asMono :: vector Float -> vector Float
-asMono = id
-
-asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)
-asStereo = id
-
-asMonoPacked :: vector Vector -> vector Vector
-asMonoPacked = id
-
-asMonoPacked16 :: vector (LLVM.Vector D16 Float) -> vector (LLVM.Vector D16 Float)
-asMonoPacked16 = id
-
-asWord32 :: vector Word32 -> vector Word32
-asWord32 = id
-
-asWord32Packed :: vector (LLVM.Vector D4 Word32) -> vector (LLVM.Vector D4 Word32)
-asWord32Packed = id
-
-
-playStereo :: Gen.T (Stereo.T (Value Float)) -> IO ()
-playStereo =
-   playStereoStream .
-   Gen.renderChunky (SVL.chunkSize 100000)
+playStereo :: Gen.T (Stereo.T (MultiValue.T Float)) -> IO ()
+playStereo sig =
+   playStereoStream . ($ SVL.chunkSize 100000) =<<
+   SigRender.run (fmap Stereo.multiValue sig)
 
 playStereoStream :: SVL.Vector (Stereo.T Float) -> IO ()
 playStereoStream = playStreamSox
 
-playMono :: Gen.T (Value Float) -> IO ()
-playMono =
-   playMonoStream .
-   Gen.renderChunky (SVL.chunkSize 100000)
-
-playMonoParam :: GenP.T () (Value Float) -> IO ()
-playMonoParam =
-   playMonoStream .
-   ($ ()) .
-   ($ SVL.chunkSize 100000) <=<
-   GenP.runChunky
+playMono :: Gen.MV Float -> IO ()
+playMono sig =
+   playMonoStream . ($ SVL.chunkSize 100000) =<< SigRender.run sig
 
-playMonoPacked :: GenP.T () VectorValue -> IO ()
+playMonoPacked :: Gen.T VectorValue -> IO ()
 playMonoPacked =
    playMonoStream .
    SigStL.unpack .
-   ($ ()) .
    ($ SVL.chunkSize 100000) <=<
-   GenP.runChunky
+   SigRender.run
 
 playMonoStream :: SVL.Vector Float -> IO ()
 playMonoStream = playStreamSox
@@ -180,9 +156,9 @@
 sampleRate :: Ring.C a => a
 sampleRate = 44100
 
-type Vector = Serial.Plain VectorSize Float
+type Vector = Serial.T VectorSize Float
 type VectorSize = TypeNum.D4
-type VectorValue = Serial.Value VectorSize Float
+type VectorValue = MultiValue.T Vector
 
 vectorSize :: Int
 vectorSize =
@@ -226,11 +202,9 @@
 
 modulation :: IO ()
 modulation = do
-   proc <-
-      CausalP.processIO
-         (0.95 * (CausalP.osciSimple Wave.approxSine4 $< 0))
+   proc <- Render.run (0.95 * (Causal.osci Wave.approxSine4 $< 0))
    playFromEvents 0.01 (0.015::Double)
-      ((proc () :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Float))
+      ((proc :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Float))
        .
        PMIDI.controllerExponential
          (ChannelMsg.toChannel 0)
@@ -241,32 +215,31 @@
 vectorBlockSize :: Double
 vectorBlockSize = fromIntegral $ 150*vectorSize
 
-subsample :: (Integral.C t) => t -> t -> State.State t t
-subsample step t =
-   State.state $ \r -> divMod (r+t) step
-{-
-   do modify (t+)
-      (q,r) <- gets (flip divMod step)
-      put r
-      return q
--}
+subsample, _subsample :: (Integral.C t) => t -> t -> State.State t t
+subsample step t  =  State.state $ \r -> divMod (r+t) step
+_subsample step t = do
+   State.modify (t+)
+   (q,r) <- State.gets (flip divMod step)
+   State.put r
+   return q
 
 subsampleBT :: EventListBT.T NonNegW.Int a -> EventListBT.T NonNegW.Int a
 subsampleBT =
    flip State.evalState NonNeg.zero .
-   EventListBT.mapTimeM (subsample (NonNegW.fromNumberMsg "vectorSize" vectorSize))
+   EventListBT.mapTimeM
+      (subsample (NonNegW.fromNumberMsg "vectorSize" vectorSize))
 
 modulationPacked :: IO ()
 modulationPacked = do
    proc <-
-      CausalP.processIO
-         (0.95 * (CausalPS.osciSimple Wave.approxSine4 $< 0)
+      Render.run
+         (0.95 * (CausalP.osci Wave.approxSine4 $< 0)
           .
           Causal.map Serial.upsample)
    playFromEvents 0.01 (vectorBlockSize/sampleRate)
       (arr SigStL.unpackStrict
        .
-       (proc () :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Vector))
+       (proc :: PIO.T (EventListBT.T NonNegW.Int Float) (SV.Vector Vector))
        .
        arr subsampleBT
        .
@@ -279,14 +252,14 @@
 bubbles :: IO ()
 bubbles = do
    proc <-
-      CausalP.processIO
-         (0.95 * (CausalP.osciSimple Wave.sine $< 0)
+      Render.run
+         (0.95 * (Causal.osci Wave.sine $< 0)
           .
           (fst.fst * (1 + snd.fst * snd))
           .
-          Arr.second (CausalP.osciSimple Wave.saw $< 0))
+          Arr.second (Causal.osci Wave.saw $< 0))
    playFromEvents 0.01 (0.015::Double)
-      ((proc () ::
+      ((proc ::
            PIO.T
               (Zip.T
                  (Zip.T
@@ -327,23 +300,23 @@
 bubblesSet :: IO ()
 bubblesSet = do
    proc <-
-      CausalP.processIOCore
+      Render.runPlugged
          (PIn.controllerSet d6)
-         (CausalP.arrayElement d0 *
-          (CausalP.osciSimple Wave.sine $< 0)
+         (Causal.arrayElement d0 *
+          (Causal.osci Wave.sine $< 0)
           .
-          (CausalP.arrayElement d1
+          (Causal.arrayElement d1
            *
-           (1 - CausalP.arrayElement d2 *
-              (CausalP.osciSimple Wave.saw $< 0) .
-              CausalP.arrayElement d3)
+           (1 - Causal.arrayElement d2 *
+              (Causal.osci Wave.saw $< 0) .
+              Causal.arrayElement d3)
            *
-           (1 - CausalP.arrayElement d4 *
-              (CausalP.osciSimple Wave.saw $< 0) .
-              CausalP.arrayElement d5)))
+           (1 - Causal.arrayElement d4 *
+              (Causal.osci Wave.saw $< 0) .
+              Causal.arrayElement d5)))
          POut.storableVector
    playFromEvents 0.01 (0.015::Double)
-      ((proc () :: PIO.T (PCS.T Int Float) (SV.Vector Float))
+      ((proc :: PIO.T (PCS.T Int Float) (SV.Vector Float))
        .
        bubbleControl)
 
@@ -357,25 +330,25 @@
 bubblesPacked :: IO ()
 bubblesPacked = do
    proc <-
-      CausalP.processIOCore
+      Render.runPlugged
          (PIn.controllerSet d6)
-         (CausalPS.arrayElement d0 *
-          (CausalPS.osciSimple Wave.approxSine4 $< 0)
+         (CausalP.arrayElement d0 *
+          (CausalP.osci Wave.approxSine4 $< 0)
           .
-          (CausalPS.arrayElement d1
+          (CausalP.arrayElement d1
            *
-           (1 - CausalPS.arrayElement d2 *
-              (CausalPS.osciSimple Wave.saw $< 0) .
-              CausalPS.arrayElement d3)
+           (1 - CausalP.arrayElement d2 *
+              (CausalP.osci Wave.saw $< 0) .
+              CausalP.arrayElement d3)
            *
-           (1 - CausalPS.arrayElement d4 *
-              (CausalPS.osciSimple Wave.saw $< 0) .
-              CausalPS.arrayElement d5)))
+           (1 - CausalP.arrayElement d4 *
+              (CausalP.osci Wave.saw $< 0) .
+              CausalP.arrayElement d5)))
          POut.storableVector
    playFromEvents 0.01 (vectorBlockSize/sampleRate)
       (arr SigStL.unpackStrict
        .
-       (proc () :: PIO.T (PCS.T Int Float) (SV.Vector Vector))
+       (proc :: PIO.T (PCS.T Int Float) (SV.Vector Vector))
        .
        arr subsamplePCS
        .
@@ -389,88 +362,79 @@
 that cannot be satisfied with @LLVM.Vector@s.
 -}
 moveAround2dLifted ::
-   (A.Transcendental v, v ~ A.Scalar v, A.PseudoModule v,
-    A.Real v, A.RationalConstant v) =>
-   Value.T v -> Value.T v -> (Value.T v, Value.T v) ->
-   CausalP.T p (v, v) (v, v)
+   (Expr.Aggregate ve vl, Algebraic.C ve, NormedEuc.Sqr ve ve) =>
+   ve -> ve -> (ve, ve) -> Causal.T (vl, vl) (vl, vl)
 moveAround2dLifted att sonicDelay ear =
-   Causal.map
-      (uncurry $ Value.unlift2 $ curry $ Spatial.moveAround att sonicDelay ear)
+   Causal.map (Spatial.moveAround att sonicDelay ear)
 
 moveAround2d ::
-   (A.Algebraic v, A.RationalConstant v) =>
-   Value.T v -> Value.T v -> (Value.T v, Value.T v) ->
-   CausalP.T p (v, v) (v, v)
+   (ve ~ Exp v, vl ~ MultiValue.T v,
+    MultiValue.Algebraic v, MultiValue.RationalConstant v) =>
+   ve -> ve -> (ve, ve) -> Causal.T (vl, vl) (vl, vl)
 moveAround2d att sonicDelay ear =
-   Causal.map $ Value.flattenFunction $
+   Causal.map $
       (\dist -> (sonicDelay*dist, 1/(att+dist)^2)) .
       euclideanNorm2d . subtract ear
 
 euclideanNorm2d ::
-   (A.Algebraic a) =>
-   (Value.T a, Value.T a) -> Value.T a
-euclideanNorm2d (x,y) =
-   Value.sqrt $ Value.square x + Value.square y
-
-mapFunc ::
-   (Value.Flatten a, Value.Flatten b) =>
-   (a -> b) ->
-   CausalP.T p (Value.Registers a) (Value.Registers b)
-mapFunc f =
-   Causal.map (Value.flattenFunction f)
+   (MultiValue.Algebraic a) =>
+   (Exp a, Exp a) -> Exp a
+euclideanNorm2d (x,y) = Expr.sqrt $ Expr.sqr x + Expr.sqr y
 
 flyChannel ::
-   (Value.T (Value Float), Value.T (Value Float)) ->
-   CausalP.T p (Value Float, (Value Float, Value Float)) (Value Float)
+   (ae ~ Exp Float, al ~ MultiValue.T Float) =>
+   (ae, ae) -> Causal.T (al, (al, al)) al
 flyChannel ear =
    ((snd ^>> moveAround2d 1 0.1 ear >>> Arr.first (negate id))
     &&&
     (Arr.second
-        (2 * ((CausalP.differentiate $# (0::Float, 0::Float))
-              >>>
-              mapFunc euclideanNorm2d))
+         (2 * (Causal.differentiate (0,0) >>> Causal.map euclideanNorm2d))
      >>>
-     CausalP.mix))
+     Causal.mix))
    >>>
    arr (\((phase,volume), speed) -> (volume, (phase,speed)))
    >>>
-   Arr.second (CausalP.osciSimple Wave.saw)
+   Arr.second (Causal.osci Wave.saw)
    >>>
-   (CausalP.envelope * 10)
+   (Causal.envelope * 10)
 
 fly :: IO ()
 fly = do
-   let slow, fast :: CausalP.T p (Value Float) (Value Float)
+   let slow, fast :: Causal.T (MultiValue.T Float) (MultiValue.T Float)
        slow =
-          Filt1.lowpassCausal $<#
-          Filt1Core.parameter (1/sampleRate::Float)
+          Filt1.lowpassCausal $<
+          Gen.constant (Filt1Core.parameter (1/sampleRate :: Exp Float))
        fast =
-          Filt1.lowpassCausal $<#
-          Filt1Core.parameter (30/sampleRate::Float)
+          Filt1.lowpassCausal $<
+          Gen.constant (Filt1Core.parameter (30/sampleRate :: Exp Float))
    proc <-
-      CausalP.processIOCore
+      Render.runPlugged
          (PIn.controllerSet d5)
-         ((CausalP.arrayElement d0 &&&
+         ((Causal.arrayElement d0 &&&
            (liftA2 (,)
-               (CausalP.arrayElement d2)
+               (Causal.arrayElement d2)
                (liftA2 (,)
-                   ((CausalP.arrayElement d3 >>> slow)
+                   ((Causal.arrayElement d3 >>> slow)
                     +
-                    CausalP.arrayElement d1 *
-                    (CausalP.fromSignal (GenP.noise 366210 0.3) >>> fast >>> fast))
-                   ((CausalP.arrayElement d4 >>> slow)
+                    Causal.arrayElement d1 *
+                    (CausalClass.fromSignal (Gen.noise 366210 0.3)
+                        >>> fast >>> fast))
+                   ((Causal.arrayElement d4 >>> slow)
                     +
-                    CausalP.arrayElement d1 *
-                    (CausalP.fromSignal (GenP.noise 234298 0.3) >>> fast >>> fast)))
+                    Causal.arrayElement d1 *
+                    (CausalClass.fromSignal (Gen.noise 234298 0.3)
+                        >>> fast >>> fast)))
             >>>
             liftA2 Stereo.cons
                (flyChannel (-1,0))
                (flyChannel ( 1,0))))
           >>>
-          CausalP.envelopeStereo)
+          Causal.envelopeStereo
+          >>^
+          Stereo.multiValue)
          POut.storableVector
    playFromEvents 0.01 (0.015::Double)
-      ((proc () :: PIO.T (PCS.T Int Float) (SV.Vector (Stereo.T Float)))
+      ((proc :: PIO.T (PCS.T Int Float) (SV.Vector (Stereo.T Float)))
        .
        MCS.filter [
           MCS.controllerExponential Ctrl.volume (0.001, 0.99) 0.2,
@@ -483,64 +447,66 @@
 
 
 flyChannelPacked ::
-   (Value.T VectorValue, Value.T VectorValue) ->
-   CausalP.T p (VectorValue, (VectorValue, VectorValue)) VectorValue
+   (ae ~ Exp Vector, al ~ VectorValue) =>
+   (ae, ae) -> Causal.T (al, (al, al)) al
 flyChannelPacked ear =
    ((snd ^>> moveAround2d 1 0.1 ear >>> Arr.first (negate id))
     &&&
     (Arr.second
-        (2 * ((CausalPS.differentiate $# (0::Float, 0::Float))
-              >>>
-              mapFunc euclideanNorm2d))
+         (2 * (CausalP.differentiate 0 *** CausalP.differentiate 0
+               >>>
+               Causal.map euclideanNorm2d))
      >>>
-     CausalP.mix))
+     Causal.mix))
    >>>
    arr (\((phase,volume), speed) -> (volume, (phase,speed)))
    >>>
-   Arr.second (CausalPS.osciSimple Wave.saw)
+   Arr.second (CausalP.osci Wave.saw)
    >>>
-   CausalP.envelope
+   Causal.envelope
    >>>
-   CausalPS.amplify 10
+   CausalP.amplify 10
 
 
 flyPacked :: IO ()
 flyPacked = do
-   let slow, fast :: CausalP.T p VectorValue VectorValue
+   let slow, fast :: Causal.T VectorValue VectorValue
        slow =
-          Filt1.lowpassCausalPacked $<#
-          Filt1Core.parameter (1/sampleRate::Float)
+          Filt1.lowpassCausalPacked $<
+          Gen.constant (Filt1Core.parameter (1/sampleRate :: Exp Float))
        fast =
-          Filt1.lowpassCausalPacked $<#
-          Filt1Core.parameter (30/sampleRate::Float)
+          Filt1.lowpassCausalPacked $<
+          Gen.constant (Filt1Core.parameter (30/sampleRate :: Exp Float))
    proc <-
-      CausalP.processIOCore
+      Render.runPlugged
          (PIn.controllerSet d5)
-         ((CausalPS.arrayElement d0 &&&
+         ((CausalP.arrayElement d0 &&&
            (liftA2 (,)
-               (CausalPS.arrayElement d2)
+               (CausalP.arrayElement d2)
                (liftA2 (,)
-                  ((CausalPS.arrayElement d3 >>> slow)
+                  ((CausalP.arrayElement d3 >>> slow)
                    +
-                   CausalPS.arrayElement d1 *
-                   (CausalP.fromSignal (GenPS.noise 366210 0.3) >>> fast >>> fast))
-                  ((CausalPS.arrayElement d4 >>> slow)
+                   CausalP.arrayElement d1 *
+                   (CausalClass.fromSignal (GenP.noise 366210 0.3)
+                        >>> fast >>> fast))
+                  ((CausalP.arrayElement d4 >>> slow)
                    +
-                   CausalPS.arrayElement d1 *
-                   (CausalP.fromSignal (GenPS.noise 234298 0.3) >>> fast >>> fast)))
+                   CausalP.arrayElement d1 *
+                   (CausalClass.fromSignal (GenP.noise 234298 0.3)
+                        >>> fast >>> fast)))
             >>>
             liftA2 Stereo.cons
                (flyChannelPacked (-1,0))
                (flyChannelPacked ( 1,0))))
           >>>
-          CausalP.envelopeStereo
-          >>>
-          Causal.map StereoInt.interleave)
+          Causal.envelopeStereo
+          >>^
+          Stereo.multiValueSerial)
          POut.storableVector
    playFromEvents 0.01 (vectorBlockSize/sampleRate)
-      (arr SigStL.unpackStereoStrict
+      (arr SigStL.unpackStrict
        .
-       (proc () :: PIO.T (PCS.T Int Float) (SV.Vector (StereoInt.T VectorSize Float)))
+       (proc :: PIO.T (PCS.T Int Float) (SV.Vector (Serial.T VectorSize (Stereo.T Float))))
        .
        arr subsamplePCS
        .
diff --git a/example/Synthesizer/LLVM/Test.hs b/example/Synthesizer/LLVM/Test.hs
--- a/example/Synthesizer/LLVM/Test.hs
+++ b/example/Synthesizer/LLVM/Test.hs
@@ -1,2005 +1,1926 @@
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE TypeFamilies #-}
-module Main where
-
-import Synthesizer.LLVM.LAC2011 ()
-
-import qualified Synthesizer.LLVM.Server.Default as Default
-import qualified Synthesizer.LLVM.Server.SampledSound as Sample
-
-import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass
-import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
-import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth
-import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev
-import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1
-import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2
-import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P
-import qualified Synthesizer.LLVM.Filter.Moog as Moog
-import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
-import qualified Synthesizer.LLVM.Filter.NonRecursive as FiltNR
-import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP
-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessValue as CausalPV
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as Func
-import qualified Synthesizer.LLVM.CausalParameterized.Helix as Helix
-import qualified Synthesizer.LLVM.Causal.ProcessValue as CausalV
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Interpolation as Interpolation
-import qualified Synthesizer.LLVM.Simple.Signal as Sig
-import qualified Synthesizer.LLVM.Simple.Value as Value
-import qualified Synthesizer.LLVM.Storable.Signal as SigStL
-import qualified Synthesizer.LLVM.Wave as Wave
-import qualified Synthesizer.LLVM.Parameter as Param
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import Synthesizer.LLVM.CausalParameterized.Functional (($&), (&|&))
-import Synthesizer.LLVM.Causal.Process (($<), ($>), ($*), ($*#))
-import Synthesizer.LLVM.Simple.Value ((%>), (%&&))
-import Synthesizer.LLVM.Parameter (($#))
-
-import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Frame as Frame
-
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Maybe as Maybe
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (Value, valueOf, Vector)
-import LLVM.Util.Arithmetic () -- Floating instance for TValue
-
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal (D4, D8, D16)
-import Type.Base.Proxy (Proxy)
-
-import qualified Synthesizer.CausalIO.Process as PIO
-import qualified Synthesizer.Causal.Class as CausalClass
-import qualified Synthesizer.Zip as Zip
-import qualified Synthesizer.State.Control as CtrlS
-import qualified Synthesizer.State.Signal as SigS
-
-import qualified Synthesizer.Plain.Filter.Recursive as FiltR
-import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core
-import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core
-
-import Control.Arrow (Arrow, arr, (&&&), (^<<), (<<^), (***))
-import Control.Category ((<<<), (.), id)
-import Control.Applicative (pure, liftA2)
-import Control.Functor.HT (void)
-import Control.Monad (when)
-
-import qualified Data.StorableVector.Lazy as SVL
-import qualified Data.StorableVector as SV
-import Foreign.Storable (Storable)
-
-import qualified Data.EventList.Relative.TimeBody  as EventList
-import qualified Data.EventList.Relative.BodyTime  as EventListBT
-import qualified Data.EventList.Relative.MixedTime as EventListMT
-import qualified Data.EventList.Relative.TimeMixed as EventListTM
-import qualified Numeric.NonNegative.Wrapper as NonNeg
-
-import qualified Sound.Sox.Option.Format as SoxOption
-import qualified Sound.Sox.Play as SoxPlay
--- import qualified Synthesizer.ALSA.Storable.Play as Play
-
-import qualified Data.NonEmpty.Class as NonEmptyC
-import qualified Data.NonEmpty as NonEmpty
-import Data.NonEmpty ((!:))
-import Data.Traversable (sequenceA)
-import Data.Word (Word32)
-import Data.List (genericLength)
-import System.Path ((</>))
-import System.Random (randomRs, mkStdGen)
-
-import qualified System.IO as IO
-import Control.Exception (bracket)
-
-import Prelude hiding (fst, snd, id, (.))
-import qualified NumericPrelude.Numeric as NP
-import qualified Prelude as P
-
-
-asMono :: vector Float -> vector Float
-asMono = id
-
-asStereo :: vector (Stereo.T Float) -> vector (Stereo.T Float)
-asStereo = id
-
-asMonoPacked :: vector (Serial.Plain D4 Float) -> vector (Serial.Plain D4 Float)
-asMonoPacked = id
-
-asMonoPacked16 :: vector (Serial.Plain D16 Float) -> vector (Serial.Plain D16 Float)
-asMonoPacked16 = id
-
-asStereoInterleaved :: vector (StereoInt.T D4 Float) -> vector (StereoInt.T D4 Float)
-asStereoInterleaved = id
-
-asWord32 :: vector Word32 -> vector Word32
-asWord32 = id
-
-asWord32Packed :: vector (Serial.Plain D4 Word32) -> vector (Serial.Plain D4 Word32)
-asWord32Packed = id
-
-
-{- |
-> playStereo (Sig.amplifyStereo 0.3 $ stereoOsciSaw 0.01)
-
-Unfortunately: If you call :reload,
-then the next attempt to play something will be answered by:
-
-ghci: JITEmitter.cpp:110: <unnamed>::JITResolver::JITResolver(llvm::JIT&): Assertion `TheJITResolver == 0 && "Multiple JIT resolvers?"' failed.
--}
-playStereo :: Sig.T (Stereo.T (Value Float)) -> IO ()
-playStereo =
-   playStereoVector .
-   Sig.renderChunky (SVL.chunkSize 100000)
-
-playStereoVector :: SVL.Vector (Stereo.T Float) -> IO ()
-playStereoVector =
-   void . SoxPlay.simple SVL.hPut SoxOption.none 44100
-
-playMono :: Sig.T (Value Float) -> IO ()
-playMono =
-   playMonoVector .
-   Sig.renderChunky (SVL.chunkSize 100000)
-
-playMonoVector :: SVL.Vector Float -> IO ()
-playMonoVector =
-   void . SoxPlay.simple SVL.hPut SoxOption.none 44100
-
-
-playFileMono :: FilePath -> IO ()
-playFileMono fileName = do
-   IO.withFile fileName IO.ReadMode $ \h ->
-      playStereo .
-      Sig.fromStorableVectorLazy .
-      asStereo . snd
-       =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h
-   return ()
-
-
-frequency :: Float -> Param.T p Float
-frequency = return
-
-{- |
-Assist GHC-7.10.3 with determining the type of causal processes.
-GHC-7.8.4 and GHC-8.0.1 do not need it.
--}
-causalP :: CausalP.T p a b -> CausalP.T p a b
-causalP = id
-
-
-constant :: Float -> IO ()
-constant y =
-   SV.writeFile "speedtest.f32" $ asMono $ flip Sig.render 1000 $ Sig.constant y
-
-saw :: IO ()
-saw =
-   SV.writeFile "speedtest.f32" $
-   asMono $
-   flip Sig.render 10000000 $
-   Sig.osciSaw 0 0.01
-
-exponential :: IO ()
-exponential =
-   SV.writeFile "speedtest.f32" $
-   asMono $
-   flip Sig.render 10000000 $
-   Sig.exponential2 50000 1
-
-triangle :: IO ()
-triangle =
-   SV.writeFile "speedtest.f32" $
-   asMono $
-   flip Sig.render 10000000 $
-   Sig.osci Wave.triangle 0.25 0.01
-
-trianglePack :: IO ()
-trianglePack =
-   SV.writeFile "speedtest.f32" $
-   asMonoPacked $
-   (\xs -> SigP.render xs (div 10000000 4) ()) $
-   Sig.map Wave.triangle $
-   SigPS.packSmall $
-   SigP.osciCore 0.25 (frequency 4.015803e-4)
-
-trianglePacked :: IO ()
-trianglePacked =
-   SV.writeFile "speedtest.f32" $
-   asMonoPacked $
-   (\xs -> SigP.render xs (div 10000000 4) ()) $
-   (causalP (CausalPS.osciSimple Wave.triangle)
-     $< SigPS.constant 0.25
-     $* SigPS.constant 0.01)
-
-triangleReplicate :: IO ()
-triangleReplicate =
-   SV.writeFile "speedtest.f32" $
-   asMonoPacked $
-   (\xs -> SigP.render xs (div 10000000 4) ()) $
-   (causalP
-     (CausalPS.shapeModOsci
-       (\k p -> do
-           x <- Wave.triangle =<< Wave.replicate k p
-           y <- Wave.approxSine4 =<< Wave.halfEnvelope p
-           A.mul x y))
-     $< SigPS.rampInf 1000000
-     $< SigPS.constant 0
-     $* SigPS.constant 0.01)
-
-rationalSine :: IO ()
-rationalSine =
-   SV.writeFile "speedtest.f32" $
-   asMonoPacked $
-   (\xs -> SigP.render xs (div 10000000 4) ()) $
-   (causalP (CausalPS.shapeModOsci Wave.rationalApproxSine1)
-     $< (0.001 + SigPS.rampInf 10000000)
-     $< SigPS.constant 0
-     $* SigPS.constant 0.01)
-
-rationalSineStereo :: IO ()
-rationalSineStereo =
-   SV.writeFile "speedtest.f32" $
-   SigStL.unpackStereoStrict $
-   asStereoInterleaved $
-   (\xs -> SigP.render xs (div 10000000 4) ()) $
-   Sig.map StereoInt.interleave $
-   liftA2 Stereo.cons
-      (causalP (CausalPS.shapeModOsci Wave.rationalApproxSine1)
-        $< (0.001 + SigPS.rampInf 10000000)
-        $< SigPS.constant (-0.25)
-        $* SigPS.constant 0.00999)
-      (causalP (CausalPS.shapeModOsci Wave.rationalApproxSine1)
-        $< (0.001 + SigPS.rampInf 10000000)
-        $< SigPS.constant 0.25
-        $* SigPS.constant 0.01001)
-
-
-pingSig :: Float -> Sig.T (Value Float)
-pingSig freq =
-   Sig.envelope
-      (Sig.exponential2 50000 1)
-      (Sig.osciSaw 0.5 freq)
-
-pingSigP :: Param.T p Float -> SigP.T p (Value Float)
-pingSigP freq =
-   SigP.envelope
-      (SigP.exponential2 50000 1)
-      (SigP.osciSaw 0.5 freq)
-
-ping :: IO ()
-ping =
-   SV.writeFile "speedtest.f32" $
-   asMono $
-   flip Sig.render 10000000 $
-   pingSig 0.01
-
-pingSigPacked :: SigP.T Float (Serial.Value D4 Float)
-pingSigPacked =
-   let freq = id
-   in  SigP.envelope
-          (SigPS.exponential2 50000 1)
-          (SigPS.osciSimple Wave.saw 0 freq)
-
-pingPacked :: IO ()
-pingPacked =
-   SV.writeFile "speedtest.f32" $
-   asMonoPacked $
-   (\xs -> SigP.render xs (div 10000000 4) 0.01) $
-   pingSigPacked
-
-pingUnpack :: IO ()
-pingUnpack =
-   SV.writeFile "speedtest.f32" $
-   asMono $
-   (\xs -> SigP.render xs 10000000 0.01) $
-   SigPS.unpack $
-   pingSigPacked
-
-pingSmooth :: IO ()
-pingSmooth =
-   SV.writeFile "speedtest-scalar.f32" $
-   asMono $
-   (\xs -> SigP.render xs 10000000 ()) $
-   (causalP Filt1.lowpassCausal
-     $< (fmap Filt1Core.Parameter $
-         1 - (Sig.exponential2 50000 1))
-     $* SigP.osciSimple Wave.triangle 0 (frequency 0.01))
-
-pingSmoothPacked :: IO ()
-pingSmoothPacked =
-   SV.writeFile "speedtest-vector.f32" $
-   asMonoPacked $
-   (\xs -> SigP.render xs (div 10000000 4) ()) $
-   (causalP Filt1.lowpassCausalPacked
-     $< (fmap Filt1Core.Parameter $
-         1 - (Sig.exponential2 (50000/4) 1))
-     $* SigPS.osciSimple Wave.triangle 0 (frequency 0.01))
-
-stereoOsciSaw :: Float -> Sig.T (Stereo.T (Value Float))
-stereoOsciSaw freq =
-   liftA2 Stereo.cons
-      (Sig.osciSaw 0.0 (freq*1.001) `Sig.mix`
-       Sig.osciSaw 0.2 (freq*1.003) `Sig.mix`
-       Sig.osciSaw 0.1 (freq*0.995))
-      (Sig.osciSaw 0.1 (freq*1.005) `Sig.mix`
-       Sig.osciSaw 0.7 (freq*0.997) `Sig.mix`
-       Sig.osciSaw 0.5 (freq*0.999))
-
-stereoOsciSawPacked :: Float -> Sig.T (Stereo.T (Value Float))
-stereoOsciSawPacked freq =
-   let mix4 =
-          Frame.mixVector .
-          flip asTypeOf (undefined :: Value (Vector D4 Float))
-   in  liftA2 Stereo.cons
-          (Sig.map mix4 $
-           Sig.osciPlain Wave.saw
-              (valueOf $ LLVM.consVector 0.0 0.2 0.1 0.4)
-              (valueOf $ fmap (freq*) $
-               LLVM.consVector 1.001 1.003 0.995 0.996))
-          (Sig.map mix4 $
-           Sig.osciPlain Wave.saw
-              (valueOf $ LLVM.consVector 0.1 0.7 0.5 0.7)
-              (valueOf $ fmap (freq*) $
-               LLVM.consVector 1.005 0.997 0.999 1.001))
-
-stereoOsciSawPacked2 :: Float -> Sig.T (Stereo.T (Value Float))
-stereoOsciSawPacked2 freq =
-   Sig.map (Frame.mixVectorToStereo .
-            flip asTypeOf (undefined :: Value (Vector D8 Float))) $
-   Sig.osciPlain (Wave.trapezoidSkew (A.fromRational' 0.2))
-      (valueOf $ LLVM.consVector 0.0 0.2 0.1 0.4 0.1 0.7 0.5 0.7)
-      (valueOf $ fmap (freq*) $
-       LLVM.consVector 1.001 1.003 0.995 0.996 1.005 0.997 0.999 1.001)
-
-stereo :: IO ()
-stereo =
-   SV.writeFile "speedtest.f32" $
-   asStereo $
-   flip Sig.render 10000000 $
-   Sig.amplifyStereo 0.25 $
-   stereoOsciSawPacked2 0.01
-
-lazy :: IO ()
-lazy =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asMono $
-   Sig.renderChunky (SVL.chunkSize 100000)
-      {- SVL.defaultChunkSize - too slow -} $
-   Sig.envelope
-      (Sig.exponential2 50000 1)
-      (Sig.osci Wave.sine 0.5 0.01 :: Sig.T (Value Float))
-
-lazyStereo :: IO ()
-lazyStereo =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asStereo $
-   Sig.renderChunky (SVL.chunkSize 100000) $
-   Sig.amplifyStereo 0.25 $
-   stereoOsciSawPacked 0.01
-
-packTake :: IO ()
-packTake =
-   SVL.writeFile "speedtest.f32" $
-   asMonoPacked $
-   flip (SigP.renderChunky (SVL.chunkSize 1000)) () $
-   SigPS.packRotate $
-   (CausalP.take 5 $*
-    SigP.osciSimple Wave.saw 0 (frequency 0.01))
-
-chord :: Float -> Sig.T (Stereo.T (Value Float))
-chord base =
-   {-
-   This exceeds available vector registers
-   and thus needs more stack accesses.
-   Thus it needs twice as much time as the simple mixing.
-   However doing all 32 oscillators in parallel
-   and mix them in one go might be still faster.
-
-   foldl1 (Sig.zipWith Frame.mixStereoV) $
-   -}
-   NonEmpty.foldBalanced Sig.mix $
-   fmap (\f -> stereoOsciSawPacked2 (base*f)) $
-   0.25 !: 1.00 : 1.25 : 1.50 : []
-
-lazyChord :: IO ()
-lazyChord =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asStereo $
-   Sig.renderChunky (SVL.chunkSize 100000) $
-   Sig.amplifyStereo 0.1 $
-   chord 0.005
-
-filterSweepComplex :: IO ()
-filterSweepComplex =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asStereo $
-   Sig.renderChunky (SVL.chunkSize 100000) $
-   Sig.amplifyStereo 0.3 $
-   Causal.apply BandPass.causal $
-   Sig.zip
-      (Sig.map (BandPass.parameter (valueOf 100)) $
-       Sig.map (\x -> 0.01 * exp (2 * return x)) $
-       Sig.osci Wave.sine 0 (0.1/44100)) $
-   chord 0.005
-
-lfoSineCausal ::
-   CausalP.T p (Value Float) a -> Param.T p Float -> SigP.T p a
-lfoSineCausal f reduct =
-   CausalP.apply f $
-   Sig.map (\x -> 0.01 * exp (2 * return x)) $
-   SigP.osciSimple Wave.sine 0 (reduct * 0.1/44100)
-
-lfoSine ::
-   (Memory.C a) =>
-   (forall r. Value Float -> LLVM.CodeGenFunction r a) ->
-   Param.T p Float ->
-   SigP.T p a
-lfoSine f = lfoSineCausal (Causal.map f)
-
-filterSweep :: IO ()
-filterSweep =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asMono $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (0.2 *
-      CtrlP.processCtrlRate 128
-         (lfoSine (Filt2.bandpassParameter (valueOf 100)))
-      $* SigP.osciSimple Wave.saw 0 (frequency 0.01))
-
-filterSweepPacked :: IO ()
-filterSweepPacked =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take (div 10000000 4) $
-   asMonoPacked $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (0.2 *
-    CtrlPS.processCtrlRate 128
-       (lfoSine (Filt2.bandpassParameter (valueOf 100)))
-      $* SigPS.osciSimple Wave.saw 0 0.01)
-
-exponentialFilter2Packed :: IO ()
-exponentialFilter2Packed =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take (div 10000000 16) $
-   asMonoPacked16 $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (causalP Filt2.causalPacked
-      $< (SigP.constant $#
-             Filt2Core.Parameter (1::Float) 0 0   0 0.99)
-      $* (
---          (CausalP.delay1 $# Serial.fromFixedList (0.1 !: 0.01 !: 0.001 !: 0.0001 !: Empty.Cons))
---          (CausalP.delay1 $# Serial.replicate (1::Float))
-          (CausalP.delay1 $# Serial.fromFixedList ((1::Float) !: NonEmptyC.repeat 0))
-           $* 0))
-
-filterSweepPacked2 :: IO ()
-filterSweepPacked2 =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asMono $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (0.2 *
-    CtrlP.processCtrlRate 128
-       (lfoSine (Filt2P.bandpassParameter (valueOf 100)))
-      $* SigP.osciSimple Wave.saw 0 (frequency 0.01))
-
-butterworthNoisePacked :: IO ()
-butterworthNoisePacked =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take (div 10000000 4) $
-   asMonoPacked $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (CausalPS.amplify 0.2 .
-    CtrlPS.processCtrlRate 128
-      (lfoSineCausal
-         (CausalClass.applyConstFst
-            (Butterworth.parameterCausal TypeNum.d3 FiltR.Lowpass)
-            (valueOf 0.5)))
-      $* SigPS.noise 0 0.3)
-
-chebyshevNoisePacked :: IO ()
-chebyshevNoisePacked =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take (div 10000000 4) $
-   asMonoPacked $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (CausalPS.amplify 0.2 .
-    CtrlPS.processCtrlRate 128
-      (lfoSineCausal
-         (CausalClass.applyConstFst
-            (Chebyshev.parameterCausalA TypeNum.d5 FiltR.Lowpass)
-            (valueOf 0.5)))
-      $* SigPS.noise 0 0.3)
-
-{-
-Provoke non-aligned vector accesses by calling alloca for a record of 5 floats
-in LLVM-2.6.
-However, the vector accesses are those of noise.
-Using scalar Noise there is no problem.
--}
-noiseAllocaBug :: IO ()
-noiseAllocaBug =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take (div 10000000 4) $
-   asMonoPacked $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (CausalPS.amplify 0.2 . Filt2.causalPacked
-      $< (Sig.map (const $ Memory.load =<< LLVM.alloca) $
-            (Sig.constant (0::Float)))
-      $* SigPS.noise 0 0.3)
-
-noiseAllocaScalar :: IO ()
-noiseAllocaScalar =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asMono $
-   flip (SigP.renderChunky (SVL.chunkSize 10000)) () $
-   (0.2 * causalP Filt2.causal
-      $< (Sig.map (const $
-             (Memory.load =<< LLVM.alloca ::
-                 LLVM.CodeGenFunction r (Filt2.Parameter (Value Float)))) $
-           (Sig.constant (0::Float)))
-      $* SigP.noise 0 0.3)
-
-
-upsample :: IO ()
-upsample =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asMono $
-   Sig.renderChunky (SVL.chunkSize 100000) $
-      (let reduct = 128 :: Float
-       in  flip Causal.applyConst reduct $ Causal.interpolateConstant $
-           Sig.osci Wave.sine 0 (reduct*0.1/44100))
-
-
-filterSweepControlRateCausal ::
-   Causal.T
-      (Stereo.T (Value Float))
-      (Stereo.T (Value Float))
-filterSweepControlRateCausal =
-   Causal.amplifyStereo 0.3 <<<
-   BandPass.causal <<<
-   Causal.feedFst
-      (let reduct = 128
-       in  flip Causal.applyConst reduct $ Causal.interpolateConstant $
-           Sig.map (BandPass.parameter (valueOf 100)) $
-           Sig.map (\x -> 0.01 * exp (2 * return x)) $
-           Sig.osci Wave.sine 0 (reduct*0.1/44100))
-
-filterSweepControlRateProc ::
-   Sig.T (Stereo.T (Value Float)) ->
-   Sig.T (Stereo.T (Value Float))
-filterSweepControlRateProc =
-   Causal.apply filterSweepControlRateCausal
-
-{- |
-Trigonometric functions are very slow in LLVM
-because they are translated to calls to C's math library.
-Thus it is advantageous to compute filter parameters
-at a lower rate and interpolate constantly.
--}
-filterSweepControlRate :: IO ()
-filterSweepControlRate =
-   SVL.writeFile "speedtest.f32" $
-   asStereo $
-   SVL.take 10000000 $
-   Sig.renderChunky (SVL.chunkSize 100000) $
-   filterSweepControlRateProc $
-   chord 0.005
-
-
-filterSweepMusic :: IO ()
-filterSweepMusic = do
-   music <- SV.readFile "lichter.f32"
-   SVL.writeFile "speedtest.f32" $
-      asStereo $
-      Sig.renderChunky (SVL.chunkSize 100000) $
-      Sig.amplifyStereo 20 $
-      filterSweepControlRateProc $
-      Sig.fromStorableVector $
-      (music :: SV.Vector (Stereo.T Float))
-
-
-playFilterSweepMusicLazy :: IO ()
-playFilterSweepMusicLazy = do
-   IO.withFile "lichter.f32" IO.ReadMode $ \h ->
-      playStereo .
---      Sig.amplifyStereo 1.125 .
-      Sig.amplifyStereo 20 .
-      filterSweepControlRateProc .
-      Sig.fromStorableVectorLazy .
-      asStereo . snd
-       =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h
-   return ()
-
-playFilterSweepMusicCausal :: IO ()
-playFilterSweepMusicCausal = do
-   music <- SV.readFile "lichter.f32"
-   _ <- SoxPlay.simple SV.hPut SoxOption.none 44100 $
-      asStereo $
-      Causal.applyStorable
-         (Causal.amplifyStereo 20 <<< filterSweepControlRateCausal) $
-      (music :: SV.Vector (Stereo.T Float))
-   return ()
-
-playFilterSweepMusicCausalLazy :: IO ()
-playFilterSweepMusicCausalLazy = do
-   IO.withFile "lichter.f32" IO.ReadMode $ \h ->
-      playStereoVector .
-      Causal.applyStorableChunky
-         (Causal.amplifyStereo 20 <<< filterSweepControlRateCausal) .
-      asStereo . snd
-       =<< SVL.hGetContentsAsync (SVL.chunkSize 43210) h
-   return ()
-
-deinterleaveProc ::
-   IO (Float ->
-       PIO.T
-         (SV.Vector (StereoInt.T D4 Float))
-         (Zip.T
-            (SV.Vector (StereoInt.T D4 Float))
-            (SV.Vector (StereoInt.T D4 Float))))
-deinterleaveProc =
-   CausalP.processIO deinterleaveCausal
-
-deinterleaveCausal ::
-   CausalP.T Float
-      (StereoInt.Value D4 Float)
-      (StereoInt.Value D4 Float, StereoInt.Value D4 Float)
-deinterleaveCausal =
-   Func.withArgs $ \input ->
-      let env =
-             Func.fromSignal $
-                0.5 * (1 + SigPS.osciSimple (Wave.triangleSquarePower 4) 0 id)
-      in  (Causal.zipWith StereoInt.envelope $& env &|& input)
-          &|&
-          (Causal.zipWith StereoInt.envelope $& (1-env) &|& input)
-
-deinterleave :: IO ()
-deinterleave = do
-   proc <- deinterleaveProc
-   runSplitProcess (proc (2/44100))
-
-
-disturbProc, disturbFMProc ::
-   IO (PIO.T
-         (SV.Vector (StereoInt.T D4 Float))
-         (Zip.T
-            (SV.Vector (StereoInt.T D4 Float))
-            (SV.Vector (StereoInt.T D4 Float))))
-disturbProc =
-   fmap ($()) $ CausalP.processIO $ crossMix disturbCausal
-
-disturbCausal, disturbFMCausal ::
-   CausalP.T p (StereoInt.Value D4 Float) (StereoInt.Value D4 Float)
-disturbCausal =
-   Func.withArgs $ \inputInt ->
-      let tone =
-             Func.fromSignal $
-                SigPS.osciSimple Wave.triangle 0 (440/44100)
-          getEnvelope x =
-             Filt1.lowpassCausalPacked $&
-                (Func.fromSignal $
-                 (SigP.constant $# Filt1Core.parameter (1/44100::Float)))
-                &|&
-                (CausalV.map abs $& x)
-          envelopedTone x = getEnvelope x * tone
-      in  Causal.map StereoInt.interleave $&
-          CausalPS.amplifyStereo 5 $&
-          Stereo.liftApplicative envelopedTone
-             (Causal.map StereoInt.deinterleave $& inputInt)
-
-disturbFMProc =
-   fmap ($()) $ CausalP.processIO $ crossMix disturbFMCausal
-
-disturbFMCausal =
-   Func.withArgs $ \inputInt ->
-      let getEnvelope x =
-             Filt1.lowpassCausalPacked $&
-                (Func.fromSignal $
-                 (SigP.constant $# Filt1Core.parameter (1/44100::Float)))
-                &|&
-                (CausalV.map abs $& x)
-          modulatedTone x =
-             getEnvelope x *
-             (CausalPS.osciSimple Wave.triangle $&
-                NP.zero
-                &|&
-                10 *
-                getEnvelope
-                   ((CausalPS.differentiate $# (0 :: Float)) $& x))
-      in  Causal.map StereoInt.interleave $&
-          CausalPS.amplifyStereo 5 $&
-          Stereo.liftApplicative modulatedTone
-             (Causal.map StereoInt.deinterleave $& inputInt)
-
-disturb :: IO ()
-disturb =
-   runSplitProcess =<< disturbFMProc
-
-
-wowFlutterProc ::
-   IO (PIO.T
-         (SV.Vector (StereoInt.T D4 Float))
-         (Zip.T
-            (SV.Vector (StereoInt.T D4 Float))
-            (SV.Vector (StereoInt.T D4 Float))))
-wowFlutterProc =
-   fmap ($()) $ CausalP.processIO $ crossMix wowFlutterCausal
-
-wowFlutterCausal ::
-   CausalP.T p (StereoInt.Value D4 Float) (StereoInt.Value D4 Float)
-wowFlutterCausal =
-   Func.withArgs $ \inputInt ->
-      let freq =
-             Func.fromSignal $ (44100*) $
-                0.01 * (1 + SigPS.osciSimple Wave.triangle 0 (1/44100 :: Param.T p Float)) +
-                0.01 * (1 + SigPS.osciSimple Wave.approxSine2 0 (1.23/44100 :: Param.T p Float))
-          modulatedTone x =
-             CausalPS.pack
-                (CausalP.delayControlledInterpolated Interpolation.linear
-                    (0 :: Param.T p Float) (441*2*2+10))
-             $&
-             freq &|& x
-      in  Causal.map StereoInt.interleave $&
-          Stereo.liftApplicative modulatedTone
-             (Causal.map StereoInt.deinterleave $& inputInt)
-
-crossMix ::
-   CausalP.T p (StereoInt.Value D4 Float) (StereoInt.Value D4 Float) ->
-   CausalP.T p
-      (StereoInt.Value D4 Float)
-      (StereoInt.Value D4 Float, StereoInt.Value D4 Float)
-crossMix proc =
-   ((fst NP.+ snd)  &&&  (fst NP.- snd))
-   .
-   (id &&& proc)
-   .
-   Causal.map (StereoInt.amplify 0.5)
-
-
-wowFlutter :: IO ()
-wowFlutter =
-   runSplitProcess =<< wowFlutterProc
-
-
-
-scrambleProc0, scrambleProc1 ::
-   IO (Float ->
-       PIO.T
-         (SV.Vector (StereoInt.T D4 Float))
-         (Zip.T
-            (SV.Vector (StereoInt.T D4 Float))
-            (SV.Vector (StereoInt.T D4 Float))))
-scrambleProc0 =
-   CausalP.processIO $
-      deinterleaveCausal NP.+
-      (id &&& NP.negate id) .
-         Causal.map (StereoInt.amplify 0.5) . wowFlutterCausal
-
-scrambleProc1 =
-   CausalP.processIO $
-      deinterleaveCausal NP.+
-      (id &&& NP.negate id) .
-         Causal.map (StereoInt.amplify 0.3) .
-         (wowFlutterCausal NP.+ disturbFMCausal)
-
-scramble :: IO ()
-scramble = do
-   proc <- scrambleProc1
-   runSplitProcess (proc (2/44100))
-
-
-runSplitProcess ::
-   (Storable a) =>
-   PIO.T (SV.Vector a) (Zip.T (SV.Vector a) (SV.Vector a)) ->
-   IO ()
-runSplitProcess proc = do
-   void $
-      IO.withFile "/tmp/test.f32" IO.ReadMode $ \h ->
-      IO.withFile "/tmp/even.f32" IO.WriteMode $ \h0 ->
-      IO.withFile "/tmp/odd.f32"  IO.WriteMode $ \h1 ->
-
-      case proc of
-         PIO.Cons next create delete ->
-            {-
-            Is the use of 'bracket' correct?
-            I think 'delete' must be called with the final state,
-            not with the initial one.
-            -}
-            bracket create delete $
-               let chunkSize = 543210
-                   loop s0 = do
-                      chunk <- SV.hGet h chunkSize
-                      (Zip.Cons y0 y1, s1) <- next chunk s0
-                      SV.hPut h0 y0
-                      SV.hPut h1 y1
-                      when
-                         (SV.length y0 >= SV.length chunk &&
-                          SV.length y1 >= SV.length chunk &&
-                          SV.length chunk >= chunkSize)
-                         (loop s1)
-               in  loop
-
-
-antimixProc ::
-   IO (SVL.Vector (StereoInt.T D4 Float) ->
-       PIO.T
-         (SV.Vector (StereoInt.T D4 Float))
-         (Zip.T
-            (SV.Vector (StereoInt.T D4 Float))
-            (SV.Vector (StereoInt.T D4 Float))))
-antimixProc =
-   CausalP.processIO $ crossMix $
-      Causal.map (StereoInt.amplify 0.5) .
-      (CausalP.fromSignal $ SigP.fromStorableVectorLazy id)
-
-antimix :: IO ()
-antimix = do
-   proc <- antimixProc
-   void $
-      IO.withFile "/tmp/test.f32" IO.ReadMode $ \h ->
-      IO.withFile "/tmp/even.f32" IO.WriteMode $ \h0 ->
-      IO.withFile "/tmp/odd.f32"  IO.WriteMode $ \h1 -> do
-         let chunkSize = SVL.chunkSize 543210
-         input <- fmap snd $ SVL.hGetContentsAsync chunkSize h
-         let vectorSize = 4
-             additive = SVL.drop (div 44100 vectorSize) input
-{-
-             additive =
-                case SVL.splitAt (div 44100 vectorSize) input of
-                   (prefix, suffix) ->
-                      SVL.append suffix $
-                      SVL.replicate chunkSize (SVL.length prefix) StereoInt.zero
--}
-{-
-             additive =
-                case SVL.splitAt (div 44100 vectorSize) input of
-                   (prefix, suffix) -> SVL.append suffix prefix
--}
-
-         case proc additive of
-            PIO.Cons next create delete ->
-               {-
-               Is the use of 'bracket' correct?
-               I think 'delete' must be called with the final state,
-               not with the initial one.
-               -}
-               bracket create delete $ \state ->
-                  let loop cs0 s0 =
-                         case cs0 of
-                            [] -> return ()
-                            c : cs -> do
-                               (Zip.Cons y0 y1, s1) <- next c s0
-                               SV.hPut h0 y0
-                               SV.hPut h1 y1
-                               when
-                                  (SV.length y0 >= SV.length c &&
-                                   SV.length y1 >= SV.length c)
-                                  (loop cs s1)
-                  in  loop (SVL.chunks input) state
-
-
-arrangeLazy :: IO ()
-arrangeLazy = do
-   IO.hSetBuffering IO.stdout IO.NoBuffering
-   arrange <- SigStL.makeArranger
-   print $
-      arrange (SVL.chunkSize 2) $
-      EventList.fromPairList $
-         (0, SVL.pack (SVL.chunkSize 2) [1,2::Double]) :
-         (0, SVL.pack (SVL.chunkSize 2) [3,4,5,6]) :
-         (2, SVL.pack (SVL.chunkSize 2) [7,8,9,10]) :
- --        repeat (2, SVL.empty)
---         (2, SVL.empty) :
---         (2, SVL.empty) :
---         (2::NonNeg.Int, error "undefined sound") :
-         error "end of list"
- --        []
-
-
-{- |
-This is inefficient because pingSig is compiled by LLVM
-for every occurence of the sound!
-
-randomTones :: IO ()
-randomTones = do
-   playMonoVector $
-      SigStL.arrange (SVL.chunkSize 12345) $
-      EventList.fromPairList $ zip
-         (cycle $ map (flip div 16 . (44100*)) [1,2,3])
-         (cycle $ map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 54321) .
-                       pingSig . (0.01*))
-          [1,1.25,1.5,2])
-   return ()
--}
-
-{- |
-So far we have not managed to compile signals
-that depend on parameters.
-Thus in order to avoid much recompilation,
-we compile and render a few sounds in advance.
--}
-pingTones :: [SVL.Vector Float]
-pingTones =
-   map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 4321) .
-        pingSig . (0.01*))
-   [1,1.25,1.5,2]
-
-pingTonesIO :: IO [SVL.Vector Float]
-pingTonesIO =
-   fmap
-      (\pingVec ->
-         map
-            (SVL.take 44100 .
-             pingVec (SVL.chunkSize 4321) .
-             (0.01*))
-            [1,1.25,1.5,2])
-      (SigP.runChunky $ pingSigP id)
-
-{-
-Arrange itself does not seem to have a space leak with temporary data.
-However it may leak sound data.
-This is not very likely because this would result in a large memory leak.
-
-Generate random tones in order to see whether generated sounds leak.
-How does 'arrange' compare with 'concat'?
--}
-
-cycleTones :: IO ()
-cycleTones = do
---   playMono $
-   pings <- pingTonesIO
-   SVL.writeFile "test.f32" $
---   Play.auto (0.01::Double) 44100 $
-      asMono $
-{-
-after 13min runtime memory consumption increased from 2.5 to 3.9
-and we get lot of buffer underruns with this implementation of amplification
-(renderChunky . amplify . fromStorableVector)
--}
-      Sig.renderChunky (SVL.chunkSize 432109) $
-      Sig.amplify 0.1 $
-      Sig.fromStorableVectorLazy $
-{-
-after 20min memory consumption increased from 2.5 to 3.4
-and we get lot of buffer underruns with applyStorableChunky
--}
-{-
-applyStorableChunky applied to concatenated zero vectors
-starts with memory consumption 1.0 and after an hour, it's still 1.1
-without buffer underruns.
--}
-{-
-      CausalP.applyStorableChunky (CausalP.amplify $# (0.1::Float)) () $
-      asMono $
--}
-{-
-with chunksize 12345678
-after 50min runtime the memory consumption increased from 12.0 to 26.2
-
-with chunksize 123
-after 25min runtime the memory consumption is constant 7.4
-however at start time there 5 buffer underruns, but no more
-probably due to initial LLVM compilation
-
-with chunksize 1234567 and SVL.replicate instead of pingTones
-we get memory consumption from 1.3 to 3.2 in 15min,
-while producing lots of buffer underruns.
-After 45min in total, it is still 3.2 of memory consumption.
-Is this a memory leak, or isn't it?
-
-with chunksize 12345678 and SVL.replicate
-we get from 5.6 to 10.2 in 3min
-to 14.9 after total 13min.
--}
-{-
-      SigStL.arrange (SVL.chunkSize 12345678) $
-      EventList.fromPairList $ zip
-         (repeat (div 44100 8))
---         (cycle $ map (flip div 4 . (44100*)) [1,2,3])
--}
-{-
-With plain concatenation of those zero vectors
-we stay constantly at 0.4 memory consumption and no buffer underruns over 30min.
--}
-      SVL.concat
-         (cycle pings)
---         (repeat $ SVL.replicate (SVL.chunkSize 44100) 44100 0)
-   return ()
-
-
-tonesChunkSize :: SVL.ChunkSize
-numTones :: Int
-
-{-
-For one-time-compiled fill functions,
-larger chunks have no relevant effect on the processing speed.
--}
-(tonesChunkSize, numTones) =
-   (SVL.chunkSize 441, 200)
---   (SVL.chunkSize 44100, 200)
-
-fst :: Arrow arrow => arrow (a,b) a
-fst = arr P.fst
-
-snd :: Arrow arrow => arrow (a,b) b
-snd = arr P.snd
-
-
-{-# NOINLINE makePing #-}
-makePing :: IO ((Float,Float) -> SVL.Vector Float)
-makePing =
-   fmap ($tonesChunkSize) $
-   SigP.runChunky $
-   Param.withTuple1 $ \(halfLife, freq) ->
-      SigP.envelope
-         (SigP.exponential2 halfLife 1)
-         (SigP.osciSaw 0.5 freq)
-
-tonesDown :: IO ()
-tonesDown = do
-   let dist = div 44100 10
-   pingp <- makePing
-   arrange <- SigStL.makeArranger
-   playMonoVector $
-      CausalP.applyStorableChunky (CausalP.amplify id) (0.03::Float) $
-      arrange tonesChunkSize $
-      EventList.fromPairList $ zip
-         (repeat (NonNeg.fromNumber dist))
-         (map (SVL.take (numTones * dist) . curry pingp 50000) $
-          iterate (0.999*) 0.01)
-   return ()
-
-
-vibes :: SigP.T (Float,Float) (Value Float)
-vibes =
-   let freq = snd
-       modDepth = fst
-       halfLife = 5000
-       -- sine = Wave.sine
-       sine = Wave.approxSine4
-   in  causalP CausalP.envelope
-         $< SigP.exponential2 halfLife 1
-         $* (((CausalP.osciSimple sine
-                $< (causalP CausalP.envelope
-                       $< SigP.exponential2 halfLife modDepth
-                       $* (CausalP.osciSimple sine
-                              $* SigP.constant (return (0::Float) &&& (2*freq)))))
-               <<<
-               CausalP.mapLinear (0.01*freq) freq
-               <<<
-               CausalP.osciSimple sine)
-             $* SigP.constant (return (0::Float, 0.0001::Float)))
-
-makeVibes :: IO ((Float,Float) -> SVL.Vector Float)
-makeVibes =
-   fmap ($tonesChunkSize) $
-   SigP.runChunky vibes
-
-vibesCycleVector :: ((Float,Float) -> SVL.Vector Float) -> IO (SVL.Vector Float)
-vibesCycleVector pingp =
-   (\evs -> fmap (\arrange -> arrange tonesChunkSize evs) SigStL.makeArranger) $
-   EventList.fromPairList $ zip
-      (repeat 5000)
-      (map (SVL.take 50000 . pingp) $
-       zip
-          (map (\k -> 0.5 * (1 - cos k)) $ iterate (0.05+) 0)
-          (cycle $ map (0.01*) [1, 1.25, 1.5, 2]))
-
-vibesCycle :: IO ()
-vibesCycle = do
-   sig <- vibesCycleVector =<< makeVibes
-   playMonoVector $
-      CausalP.applyStorableChunky (CausalP.amplify id) (0.2::Float) sig
-   return ()
-
-vibesEcho :: IO ()
-vibesEcho = do
-   sig <- vibesCycleVector =<< makeVibes
-   playMonoVector $
-      CausalP.applyStorableChunky
-         (CausalP.amplify id <<<
-          CausalP.comb (0.5 :: Param.T p Float) 7000)
-         (0.2::Float) sig
-   return ()
-
-vibesReverb :: IO ()
-vibesReverb = do
-   sig <- vibesCycleVector =<< makeVibes
-   playMonoVector $
-      CausalP.applyStorableChunky
-         (CausalP.amplify id <<<
-          CausalP.reverbSimple (mkStdGen 142) 16 (0.9,0.97) (400,1000))
-         (0.3::Float) sig
-   return ()
-
-vibesReverbEfficient :: IO ()
-vibesReverbEfficient = do
-   sig <- vibesCycleVector =<< makeVibes
-   playMonoVector $
-      CausalP.applyStorableChunky
-         (CausalP.amplify id <<<
-          (CausalP.reverb $# mkStdGen 142 $# 16 $# (0.9,0.97) $# (400,1000)))
-         (0.3::Float) sig
-   return ()
-
-vibesReverbStereo :: IO ()
-vibesReverbStereo = do
-   sig <- vibesCycleVector =<< makeVibes
-   void $ playStereoVector $
-      CausalP.applyStorableChunky
-         (CausalP.stereoFromMonoParameterized
-             (\amp seed ->
-                CausalP.amplify amp
-                <<<
-                CausalP.reverb (fmap mkStdGen seed)
-                   16 (pure (0.9,0.97)) (pure (400,1000)))
-             (pure $ Stereo.cons 142 857)
-          <<^
-          (\x -> Stereo.cons x x))
-         (0.3::Float) sig
-
-
-
-stair :: IO ()
-stair =
-   SVL.writeFile "speedtest.f32" $
-   SVL.take 10000000 $
-   asMono $
-   flip (SigP.renderChunky tonesChunkSize) () $
-   SigP.piecewiseConstant $
-   return $
-   EventListBT.fromPairList $
-   zip
-      (iterate (/2) (1::Float))
-      (iterate (2*) (1::NonNeg.Int))
-
-
-filterBass :: IO ()
-filterBass =
-   void $
-   playStereoVector $
-      asStereo $
-      flip (SigP.renderChunky tonesChunkSize) () $
-      CausalP.apply
-         (BandPass.causal
-          <<<
-          CausalP.feedSnd
-             (liftA2 Stereo.cons
-                 (SigP.osciSimple Wave.saw 0 (frequency 0.001499))
-                 (SigP.osciSimple Wave.saw 0 (frequency 0.001501)))
-          <<<
-          Causal.map (BandPass.parameter (valueOf (100::Float)))) $
-      SigP.piecewiseConstant $
-      return $ EventListBT.fromPairList $
-      zip
-         (map (((0.01::Float)*) . (2**) . (/12) . fromInteger) $
-          randomRs (0,24) (mkStdGen 998))
-         (repeat (6300::NonNeg.Int))
-
-
-{- |
-This function is not very efficient,
-since it compiles an LLVM mixing routine
-for every pair of mixer inputs.
--}
-mixVectorRecompile ::
-   SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float
-mixVectorRecompile xs ys =
-   Sig.renderChunky tonesChunkSize $
-   Sig.mix
-      (Sig.fromStorableVectorLazy xs)
-      (Sig.fromStorableVectorLazy ys)
-
-mixVectorParamIO ::
-   IO (SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float)
-mixVectorParamIO =
-   fmap curry $
-   fmap ($tonesChunkSize) $
-   SigP.runChunky
-      (SigP.mix
-         (SigP.fromStorableVectorLazy fst)
-         (SigP.fromStorableVectorLazy snd))
-
-mixVectorCausalIO ::
-   IO (SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float)
-mixVectorCausalIO =
-   CausalP.runStorableChunky
-      (CausalP.mix $<
-       SigP.fromStorableVectorLazy id)
-
-mixVectorCausal ::
-   SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float
-mixVectorCausal =
-   CausalP.applyStorableChunky
-      (CausalP.mix $<
-       SigP.fromStorableVectorLazy id)
-
-mixVectorStereo ::
-   SVL.Vector (Stereo.T Float) ->
-   SVL.Vector (Stereo.T Float) ->
-   SVL.Vector (Stereo.T Float)
-mixVectorStereo =
-   CausalP.applyStorableChunky
-      (CausalP.mix $< SigP.fromStorableVectorLazy id)
-
-mixVectorStereoIO ::
-   IO (SVL.Vector (Stereo.T Float) ->
-       SVL.Vector (Stereo.T Float) ->
-       SVL.Vector (Stereo.T Float))
-mixVectorStereoIO =
-   CausalP.runStorableChunky
-      (CausalP.mix $< SigP.fromStorableVectorLazy id)
-
-{-
-slightly slower than mixVectorParam
--}
-mixVectorHaskell ::
-   SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float
-mixVectorHaskell = SVL.zipWith (+)
-
-toneMix :: IO ()
-toneMix = do
-   pingp <- makePing
-   mix <- mixVectorCausalIO
-   playMonoVector $
-      Causal.applyStorableChunky (Causal.amplify 0.1) $
-      foldl1 mix $
-      map (curry pingp 1000000) $
-      take numTones $
-      iterate (*(2/3)) 0.01
-   return ()
-
-fadeEnvelope :: SigP.T (Int, Int) (Value Float)
-fadeEnvelope =
-   let dur :: Param.T (Int, Int) Float
-       dur = fmap fromIntegral fst
-   in  SigP.parabolaFadeIn dur
-       `SigP.append`
-       (CausalP.take snd $* Sig.constant 1)
-       `SigP.append`
-       SigP.parabolaFadeOut dur
-
-fadeEnvelopeWrite :: IO ()
-fadeEnvelopeWrite =
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   SigP.renderChunky (SVL.chunkSize 1234)
-   fadeEnvelope (100000, 200000)
-
-
--- | normalize a list of numbers, such that they have a specific average
--- Cf. haskore-supercollider/src/Haskore/Interface/SuperCollider/Example.hs
-normalizeLevel :: Fractional a => a -> [a] -> [a]
-normalizeLevel newAvrg xs =
-   let avrg = sum xs / genericLength xs
-   in  map ((newAvrg-avrg)+) xs
-
-stereoOsciSawP :: SigP.T Float (Stereo.T (Value Float))
-stereoOsciSawP =
-   let n = 5
-       volume :: Float
-       volume = recip $ sqrt $ fromIntegral n
-       detunes :: [Float]
-       detunes =
-          normalizeLevel 1 $ take (2*n) $
-             randomRs (0,0.03) $ mkStdGen 912
-       phases :: [Float]
-       phases = randomRs (0,1) $ mkStdGen 54
-   in  stereoFromMonoParameterizedSignal
-          (\_ params ->
-              (SigP.amplify $# volume) $
-              multiMixSignal
-                 (\_ phaseFreq ->
-                     SigP.osciSaw
-                        (fmap fst phaseFreq)
-                        (fmap snd phaseFreq))
-                 params)
-          (arr
-              (\freq ->
-                 uncurry Stereo.cons $ splitAt n $
-                 zipWith
-                    (\phase detune -> (phase, detune*freq))
-                    phases detunes))
-
-stereoFromMonoParameterizedSignal ::
-   (forall q. Param.T q p -> Param.T q x -> SigP.T q (Value Float)) ->
-   Param.T p (Stereo.T x) -> SigP.T p (Stereo.T (Value Float))
-stereoFromMonoParameterizedSignal f ps =
-   CausalP.toSignal $
-      CausalP.stereoFromMonoParameterized (\p -> CausalP.fromSignal . f p) ps
-      <<^
-      (\() -> Stereo.cons () ())
-
-multiMixSignal ::
-   (forall q. Param.T q p -> Param.T q x -> SigP.T q (Value Float)) ->
-   Param.T p [x] -> SigP.T p (Value Float)
-multiMixSignal f =
-   CausalP.toSignal . multiMix (\p x -> CausalP.fromSignal $ f p x)
-
-multiMix ::
-   (forall q. Param.T q p -> Param.T q x -> CausalP.T q a (Value Float)) ->
-   Param.T p [x] -> CausalP.T p a (Value Float)
-multiMix f ps =
-   CausalP.replicateControlledParam
-      (\p x -> CausalP.mix <<< CausalP.first (f p x)) ps
-   <<^
-   (\a -> (a, A.zero))
-
-stereoOsciSawVector :: Float -> SVL.Vector (Stereo.T Float)
-stereoOsciSawVector =
-   SigP.renderChunky tonesChunkSize stereoOsciSawP
-
-stereoOsciSawChord :: NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float)
-stereoOsciSawChord =
-   NonEmpty.foldBalanced mixVectorStereo . fmap stereoOsciSawVector
-
-stereoOsciSawPad :: Int -> NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float)
-stereoOsciSawPad dur pitches =
-   let attack = 20000
-   in  CausalP.applyStorableChunky
-          (CausalP.envelopeStereo $< fadeEnvelope)
-          (attack, dur-attack)
-          (stereoOsciSawChord pitches)
-
-a0, as0, b0, c1, cs1, d1, ds1, e1, f1, fs1, g1, gs1,
- a1, as1, b1, c2, cs2, d2, ds2, e2, f2, fs2, g2, gs2,
- a2, as2, b2, c3, cs3, d3, ds3, e3, f3, fs3, g3, gs3,
- a3, as3, b3, c4, cs4, d4, ds4, e4, f4, fs4, g4, gs4 :: Float
-a0 : as0 : b0 : c1 : cs1 : d1 : ds1 : e1 : f1 : fs1 : g1 : gs1 :
- a1 : as1 : b1 : c2 : cs2 : d2 : ds2 : e2 : f2 : fs2 : g2 : gs2 :
- a2 : as2 : b2 : c3 : cs3 : d3 : ds3 : e3 : f3 : fs3 : g3 : gs3 :
- a3 : as3 : b3 : c4 : cs4 : d4 : ds4 : e4 : f4 : fs4 : g4 : gs4 : _ =
-  iterate ((2 ** recip 12) *) (55/44100)
-
-
-chordSequence :: [(Int, NonEmpty.T [] Float)]
-chordSequence =
-   (2, f1  !: f2  : a2 : c3 : []) :
-   (1, g1  !: g2  : b2 : d3 : []) :
-   (2, c2  !: g2  : c3 : e3 : []) :
-   (1, f1  !: a2  : c3 : f3 : []) :
-   (2, g1  !: g2  : b2 : d3 : []) :
-   (1, gs1 !: gs2 : b2 : e3 : []) :
-   (2, a1  !: e2  : a2 : c3 : []) :
-   (1, g1  !: g2  : b2 : d3 : []) :
-   (3, c2  !: g2  : c3 : e3 : []) :
-
-   (2, f1  !: f2  : a2 : c3 : []) :
-   (1, g1  !: g2  : b2 : d3 : []) :
-   (2, c2  !: g2  : c3 : e3 : []) :
-   (1, f1  !: a2  : c3 : f3 : []) :
-   (2, g1  !: g2  : b2 : d3 : []) :
-   (1, gs1 !: gs2 : b2 : e3 : []) :
-   (2, a1  !: e2  : a2 : c3 : []) :
-   (1, g1  !: g2  : b2 : e3 : []) :
-   (3, c2  !: e2  : g2 : c3 : []) :
-   []
-
-
-withDur :: (Int -> a -> v) -> Int -> a -> (v, NonNeg.Int)
-withDur f d ps =
-   let dur = d*30000
-   in  (f dur ps, NonNeg.fromNumber dur)
-
-
-padMusic :: IO ()
-padMusic = do
-   arrange <- SigStL.makeArranger
-   playStereoVector $
-      CausalP.applyStorableChunky (CausalP.amplifyStereo id) (0.1::Float) $
-      arrange tonesChunkSize $
-      EventListTM.switchTimeR const $
-      EventListMT.consTime 0 $
-      EventListBT.fromPairList $
-      map (\(d,ps) -> withDur stereoOsciSawPad d ps)
-      chordSequence
-   return ()
-
-
-lowpassSweepControlRateCausal ::
-   CausalP.T p
-      (Stereo.T (Value Float))
-      (Stereo.T (Value Float))
-lowpassSweepControlRateCausal =
---   CausalP.stereoFromVector $
-   CausalP.stereoFromMono $
-      UniFilter.lowpass ^<<
-      CtrlP.processCtrlRate 128
-         (lfoSine (UniFilter.parameter (valueOf (10::Float))))
-
-
-moogSweepControlRateCausal ::
-   CausalP.T p
-      (Stereo.T (Value Float))
-      (Stereo.T (Value Float))
-moogSweepControlRateCausal =
---   CausalP.stereoFromVector $
-   CausalP.stereoFromMono $
-      CtrlP.processCtrlRate 128
-         (lfoSine (Moog.parameter TypeNum.d8 (valueOf (10::Float))))
-
-
-filterMusic :: IO ()
-filterMusic = do
-   arrange <- SigStL.makeArranger
-   pad <- stereoOsciSawPadIO
-   void $ playStereoVector $
-      CausalP.applyStorableChunky
-         (CausalP.amplifyStereo id <<<
-          moogSweepControlRateCausal) (0.05::Float) $
-      arrange tonesChunkSize $
-      EventListTM.switchTimeR const $
-      EventListMT.consTime 0 $
-      EventListBT.fromPairList $
-      map (\(d,ps) -> withDur pad d ps)
-      chordSequence
-
-
-
-stereoOsciSawVectorIO :: IO (Float -> SVL.Vector (Stereo.T Float))
-stereoOsciSawVectorIO =
-   fmap ($tonesChunkSize) $
-   SigP.runChunky $
-   stereoOsciSawP
-
-applyFadeEnvelopeIO ::
-   IO (Int -> SVL.Vector (Stereo.T Float) -> SVL.Vector (Stereo.T Float))
-applyFadeEnvelopeIO =
-   fmap
-      (\envelope dur sig ->
-         let attack = 20000
-         in  envelope (attack, dur-attack) sig)
-      (CausalP.runStorableChunky
-         (CausalP.envelopeStereo $< fadeEnvelope))
-
-stereoOsciSawChordIO :: IO (NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float))
-stereoOsciSawChordIO = do
-   sawv <- stereoOsciSawVectorIO
-   mix <- mixVectorStereoIO
-   return (NonEmpty.foldBalanced mix . fmap sawv)
-
-stereoOsciSawPadIO ::
-   IO (Int -> NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float))
-stereoOsciSawPadIO = do
-   chrd <- stereoOsciSawChordIO
-   envelope <- applyFadeEnvelopeIO
-   return $
-      \ dur pitches -> envelope dur (chrd pitches)
-
-padMusicIO :: IO ()
-padMusicIO = do
-   arrange <- SigStL.makeArranger
-   pad <- stereoOsciSawPadIO
-   playStereoVector $
-      CausalP.applyStorableChunky (CausalP.amplifyStereo id) (0.08::Float) $
-      arrange tonesChunkSize $
-      EventListTM.switchTimeR const $
-      EventListMT.consTime 0 $
-      EventListBT.fromPairList $
-      map (uncurry (withDur pad)) $
-      chordSequence
-   return ()
-
-{-
-Apply the envelope separately to each tone of the chord
-and mix all tones by 'arrange'.
--}
-padMusicSeparate :: IO ()
-padMusicSeparate = do
-   arrange <- SigStL.makeArranger
-   osci <- stereoOsciSawVectorIO
-   env <- applyFadeEnvelopeIO
-   playStereoVector $
-      CausalP.applyStorableChunky (CausalP.amplifyStereo id) (0.08::Float) $
-      arrange tonesChunkSize $
-      EventList.flatten $
-      EventListTM.switchTimeR const $
-      EventListMT.consTime 0 $
-      EventListBT.fromPairList $
-      map (uncurry (withDur (\d ps ->
-         map (\p -> env d (osci p)) $ NonEmpty.flatten ps))) $
-      chordSequence
-   return ()
-
-
-delay :: IO ()
-delay =
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   flip (SigP.renderChunky tonesChunkSize) (0, 10000) $
-   (CausalP.delayZero fst . CausalP.take snd
-    $*
-    SigP.osciSaw 0 (frequency 0.01))
-
-delayStereo :: IO ()
-delayStereo =
-   SVL.writeFile "speedtest.f32" $
-   asStereo $
-   flip (SigP.renderChunky tonesChunkSize) (7, 10000) $
-   (CausalP.take snd . liftA2 Stereo.cons id (CausalP.delayZero fst)
-    $*
-    SigP.osciSaw 0 (frequency 0.01))
-
-delayPhaser :: IO ()
-delayPhaser =
-   SVL.writeFile "speedtest.f32" $
-   asStereo $
-   flip (SigP.renderChunky tonesChunkSize) 40000 $
-   Func.compileSignal $
-      let osci = Func.fromSignal $ SigP.osciSaw 0 (frequency 0.01)
-          ctrl =
-             Func.fromSignal $
-             SigP.osciSimple Wave.triangle 0 $ frequency (1/20000)
-      in  CausalP.take id $&
-          liftA2 Stereo.cons
-             osci
-             (CausalP.delayControlledInterpolated Interpolation.cubic
-                 (0 :: Param.T p Float) 100
-              $&
-              (50+50*ctrl) &|& osci)
-
-
-
-allpassControl ::
-   (TypeNum.Natural n) =>
-   Proxy n ->
-   SigP.T Float (Allpass.CascadeParameter n (Value Float))
-allpassControl order =
-   let reduct = id
-   in  SigP.interpolateConstant reduct $
-       lfoSine (Allpass.flangerParameter order) reduct
-
-allpassPhaserCausal, allpassPhaserPipeline ::
-   SigP.T Float (Value Float) ->
-   SigP.T Float (Value Float)
-allpassPhaserCausal =
-   let order = TypeNum.d16
-   in  CausalP.apply
-          (0.5 * Allpass.phaser $< allpassControl order)
-
-allpassPhaserPipeline =
-   let order = TypeNum.d16
-   in  -- (F.nest (TypeNum.integralFromProxy order) SigP.tail .) $
-       SigP.drop (return $ TypeNum.integralFromProxy order) .
-       CausalP.apply
-          (0.5 * Allpass.phaserPipeline $< allpassControl order)
-
-allpassPhaser :: IO ()
-allpassPhaser =
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) 128 $
-   allpassPhaserPipeline $
-   SigP.osciSaw 0 (frequency 0.01)
-
-noise :: IO ()
-noise =
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   SigP.noise 0 0.3
-
-noisePacked :: IO ()
-noisePacked =
-   SVL.writeFile "speedtest.f32" $
-   asMonoPacked $
-   SVL.take (div 10000000 4) $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   SigPS.noise 0 0.3
---   SigPS.pack (SigP.noise 0 0.3)
---   SigPS.packSmall (SigP.noise 0 0.3)
-
-frequencyModulationStorable :: IO ()
-frequencyModulationStorable = do
-   smp <- SigP.runChunky (SigP.osciSaw 0 (frequency 0.01))
-   SVL.writeFile "speedtest.f32" $
-      asMono $
-      flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-      (CausalP.frequencyModulationLinear
-          (SigP.fromStorableVectorLazy $#
-           (SVL.take 1000000 $ asMono $
-            smp (SVL.chunkSize 1000) ()))
-       $*# (0.3::Float))
-
-frequencyModulation :: IO ()
-frequencyModulation =
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   (CausalP.frequencyModulationLinear
-       (SigP.osciSaw 0 (frequency 0.01))
-    $* Sig.exponential2 500000 1)
-
-frequencyModulationStereo :: IO ()
-frequencyModulationStereo = do
-   smp <- SigP.runChunky (SigP.osciSaw 0 (frequency 0.01))
-   SVL.writeFile "speedtest.f32" $
-      asStereo $
-      flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-      (CausalP.stereoFromMono
-         (CausalP.frequencyModulationLinear
-            (SigP.fromStorableVectorLazy $#
-             (SVL.take 1000000 $ asMono $
-              smp (SVL.chunkSize 1000) ())))
-       $*# Stereo.cons (0.2999::Float) 0.3001)
-
-frequencyModulationProcess :: IO ()
-frequencyModulationProcess =
-   SVL.writeFile "speedtest.f32" .
-   asMono .
-   (\f ->
-      f () $ asMono $
-      SigP.renderChunky (SVL.chunkSize 512)
-         (1 + 0.1 * SigP.osciSimple Wave.approxSine2 (pure (0::Float)) 0.0001)
-         ()) =<<
-   CausalP.runStorableChunky
-      (CausalP.frequencyModulationLinear
-          (CausalP.take 50000 $*
-           SigP.osciSaw 0 (frequency 0.01)))
-
-
-
-quantize :: IO ()
-quantize =
-{-
-   SV.writeFile "speedtest.f32" $
-   asMono $
-   (\xs -> SigP.render xs 10000000 ()) $
--}
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   ((CausalP.quantizeLift $# (5.5::Float)) id $*
-    SigP.osciSaw 0 (frequency 0.01))
-
-quantizedFilterControl :: IO ()
-quantizedFilterControl =
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   CausalP.apply (0.3 * (UniFilter.lowpass ^<< CtrlP.process)) $
-   SigP.zip
-      ((CausalP.quantizeLift $# (128::Float))
-         (Causal.map (UniFilter.parameter (valueOf 100)) <<<
---         (Causal.map (Moog.parameter TypeNum.d8 (valueOf 100)) <<<
-          CausalV.map (\x -> 0.01 * exp (2 * x)))
-         $* SigP.osciSimple Wave.approxSine2 0 (frequency (0.1/44100))) $
-   SigP.osciSaw 0 (frequency 0.01)
-
-
-arrowNonShared :: IO ()
-arrowNonShared =
-   SVL.writeFile "speedtest.f32" $
-   asStereo $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   (let osci = CausalP.osciSimple Wave.approxSine2
-    in  liftA2 Stereo.cons osci osci $*
-        SigP.constant (return (0::Float, 0.01::Float)))
-
-arrowShared :: IO ()
-arrowShared =
-   SVL.writeFile "speedtest.f32" $
-   asStereo $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   (let osci = Func.lift (CausalP.osciSimple Wave.approxSine2)
-    in  Func.compile (liftA2 Stereo.cons osci osci) $*
-        SigP.constant (return (0::Float, 0.01::Float)))
-
-arrowIndependent :: IO ()
-arrowIndependent =
-   SVL.writeFile "speedtest.f32" $
-   asStereo $
-   SVL.take 10000000 $
-   flip (SigP.renderChunky (SVL.chunkSize 100000)) () $
-   (let osci = CausalP.osciSimple Wave.approxSine2
-    in  Func.compile
-          (fmap (uncurry Stereo.cons)  $
-           osci *** osci  $&
-           Func.lift id) $*
-        SigP.constant (return ((0::Float, 0.01::Float), (0.25::Float, 0.01001::Float))))
-
-
-rampDown :: Int -> SV.Vector Float
-rampDown n =
-   SigS.toStrictStorableSignal n $
-   CtrlS.line n (1, 0)
-
-impulses :: Int -> Float -> SVL.Vector Float
-impulses n x =
-   SVL.fromChunks $
-   concatMap (\k -> [SV.singleton x, SV.replicate k 0]) $
-   take n $ iterate (2*) 1
-
-convolution :: IO ()
-convolution =
-   SVL.writeFile "speedtest.f32" $
-   asMono $
-   CausalP.applyStorableChunky
-      (FiltNR.convolve id)
-      (rampDown 1000)
-      (impulses 18 0.1)
-
-convolutionPacked :: IO ()
-convolutionPacked =
-   SVL.writeFile "speedtest.f32" $
-   asMonoPacked $
-   CausalP.applyStorableChunky
-      (FiltNR.convolvePacked id)
-      (rampDown 1000)
-      (asMonoPacked $
-       (\xs -> SigP.renderChunky SVL.defaultChunkSize xs ()) $
-       SigPS.pack $
-       SigP.fromStorableVectorLazy $
-       pure $ impulses 18 0.1)
-
-
-
-helixSaw :: IO ()
-helixSaw = do
-   let srcFreq = 0.01
-       srcLength :: Float
-       srcLength = 40000
-   osci <- SigP.run $ SigP.osciSaw 0 (pure srcFreq) * (1-SigP.ramp id)
-   let perc = asMono $ osci (round srcLength) srcLength
-   SV.writeFile "osci-saw.f32" perc
-   stretched <-
-      SigP.runChunky $
-      Func.compileSignal $
-      (Helix.static Interpolation.cubic Interpolation.cubic
-          100 (pure $ recip srcFreq) snd
-       $&
-       (Func.fromSignal $ Sig.amplify srcLength $ SigP.ramp fst)
-       &|&
-       (CausalP.osciCore $& 0 &|& 0.01))
-   SVL.writeFile "osci-stretched.f32" $ asMono $
-      stretched SVL.defaultChunkSize (80000 :: Float, perc)
-
-
-loadTomato :: IO (Float, SVL.Vector Float)
-loadTomato = do
-   let Sample.Info name _sampleRate positions = Sample.tomatensalat
-   word <- Sample.load (Default.sampleDirectory </> name)
-   return (Sample.period $ head positions, word)
-
-helixOsci :: Param.T p Float -> Func.T p a (Value Float)
-helixOsci period =
-   CausalP.osciCore $&
-      0 &|& Func.fromSignal (SigP.constant (recip period))
-
-helixSpeechStaticSig ::
-   Func.T p () (Value Float) ->
-   Param.T p (SVL.Vector Float) ->
-   Param.T p Float ->
-   SigP.T p (Value Float)
-helixSpeechStaticSig shape word period =
-   Func.compileSignal
-      (Helix.static Interpolation.linear Interpolation.linear
-          (fmap round period) period
-          (fmap (SV.concat . SVL.chunks) word)
-       $&
-       shape
-       &|&
-       helixOsci period)
-
-helixSpeechStaticSpeed ::
-   Param.T p Float ->
-   Param.T p (SVL.Vector Float) ->
-   Param.T p Float ->
-   SigP.T p (Value Float)
-helixSpeechStaticSpeed speed word =
-   helixSpeechStaticSig
-      (Func.fromSignal
-         (CausalPV.takeWhile (%>)
-             (fmap ((fromIntegral :: Int -> Float) . SVL.length) word) $*
-          SigP.rampSlope speed))
-      word
-
-helixSpeechStatic :: IO ()
-helixSpeechStatic = do
-   smp <- loadTomato
-   stretched <-
-      SigP.runChunky $
-      Param.withTuple1 $ \(speed, (period, word)) ->
-      helixSpeechStaticSpeed speed word period
-   SVL.writeFile "speech-stretched.f32" $ asMono $
-      stretched SVL.defaultChunkSize (0.5, smp)
-
-helixSpeechDynamicSig ::
-   Func.T p () (Value Float) ->
-   Param.T p (SVL.Vector Float) ->
-   Param.T p Float ->
-   SigP.T p (Value Float)
-helixSpeechDynamicSig shape word period =
-   Func.compileSignal
-      (Helix.dynamicLimited Interpolation.linear Interpolation.linear
-          (fmap round period) period (SigP.fromStorableVectorLazy word)
-       $&
-       shape
-       &|&
-       helixOsci period)
-
-helixSpeechDynamicSpeed ::
-   Param.T p Float ->
-   Param.T p (SVL.Vector Float) ->
-   Param.T p Float ->
-   SigP.T p (Value Float)
-helixSpeechDynamicSpeed speed =
-   helixSpeechDynamicSig (Func.fromSignal $ SigP.constant speed)
-
-helixSpeechDynamic :: IO ()
-helixSpeechDynamic = do
-   smp <- loadTomato
-   stretched <-
-      SigP.runChunky $
-      Param.withTuple1 $ \(speed, (period, word)) ->
-      helixSpeechDynamicSpeed speed word period
-   SVL.writeFile "speech-stretched.f32" $ asMono $
-      stretched SVL.defaultChunkSize (0.5, smp)
-
-helixSpeechCompare :: IO ()
-helixSpeechCompare = do
-   smp <- loadTomato
-   stretched <-
-      SigP.runChunky $
-      Param.withTuple1 $ \(speed, (period, word)) ->
-      sequenceA $
-      Stereo.cons
-         (helixSpeechStaticSpeed speed word period)
-         (helixSpeechDynamicSpeed speed word period)
-   SVL.writeFile "speech-stretched.f32" $ asStereo $
-      stretched SVL.defaultChunkSize (0.5, smp)
-
-helixSpeechVariCompare :: IO ()
-helixSpeechVariCompare = do
-   smp <- loadTomato
-   stretched <-
-      SigP.runChunky $
-      Param.withTuple1 $ \(period, word) ->
-      sequenceA $
-      let speed =
-             Func.fromSignal $ SigP.cycle $
-             SigP.fromStorableVector $ pure $
-             SV.pack [0.2, 0.5, 1, 1.5, 1.8 :: Float]
-      in  Stereo.cons
-             (helixSpeechStaticSig
-                 ((CausalP.integrate $# (0::Float)) $& speed) word period)
-             (helixSpeechDynamicSig speed word period)
-   SVL.writeFile "speech-stretched.f32" $ asStereo $
-      stretched SVL.defaultChunkSize smp
-
-
-helixLimited :: IO ()
-helixLimited = do
-   let period = 100
-       srcLength = 500
-       dstLength = 5000
-       speed :: Param.T p Float
-       speed = 0.5
-       osci =
-          0.5
-          *
-          SigP.ramp (pure (fromIntegral srcLength :: Float))
-          *
-          SigP.osciSimple Wave.approxSine2 0 (recip period)
-   renderOsci <- SigP.run osci
-   let osciVec = renderOsci srcLength ()
-   SV.writeFile "helix-orig.f32" $ asMono osciVec
-
-   let stretchedStatic =
-          Helix.static Interpolation.linear Interpolation.linear
-             (fmap round period) period (pure osciVec)
-          $&
-          Func.fromSignal (SigP.rampSlope speed)
-          &|&
-          helixOsci period
-       stretchedDynamic =
-          Helix.dynamic Interpolation.linear Interpolation.linear
-             (fmap round period) period osci
-          $&
-          Func.fromSignal (SigP.constant speed)
-          &|&
-          helixOsci period
-       stretched = liftA2 Stereo.cons stretchedStatic stretchedDynamic
-   renderHelix <- SigP.run $ Func.compileSignal stretched
-   SV.writeFile "helix-stretched.f32" $ asStereo $ renderHelix dstLength ()
-
-
-cycleRamp :: IO ()
-cycleRamp =
-   SVL.writeFile "speedtest.f32" . asMono .
-         (\f -> f SVL.defaultChunkSize (10000::Float)) =<<
-      SigP.runChunky
-         (CausalP.take 100000 $*
-          (SigP.cycle $ SigP.append (SigP.ramp id) (1 - SigP.ramp id)))
-
-zigZag :: IO ()
-zigZag =
-   SVL.writeFile "speedtest.f32" . asMono .
-         (\f -> f SVL.defaultChunkSize (-3::Float)) =<<
-      SigP.runChunky
-         (CausalP.take 100000 $* (Helix.zigZag id $* 0.0001))
-
-zigZagPacked :: IO ()
-zigZagPacked =
-   SVL.writeFile "speedtest.f32" . asMonoPacked .
-         (\f -> f SVL.defaultChunkSize (-3::Float)) =<<
-      SigP.runChunky
-         (let vectorSize = 4
-          in  CausalP.take (pure $ div 100000 vectorSize) $*
-              (Helix.zigZagPacked id $* 0.0001))
-
-
-trigger :: IO ()
-trigger =
-   SVL.writeFile "speedtest.f32" . asMono .
-         (\f -> f SVL.defaultChunkSize (0.01 :: Float)) =<<
-      SigP.runChunky
-         (let pause len =
-                 CausalClass.applyConst (CausalP.take len) Maybe.nothing
-              pulse :: Float -> Param.T p Int -> SigP.T p (Maybe.T (Value Float))
-              pulse freq len =
-                 CausalP.take len .
-                 arr (flip Maybe.fromBool (valueOf freq)) .
-                 CausalP.delay1 (pure True) $*# False
-          in  Sig.zipWith (flip Maybe.select) (SigP.noise 0 0.01) $
-              (CausalP.trigger
-                  (\_ freq -> CausalP.take 150000 $* pingSigP freq) $*
-               pause 50000 `SigP.append`
-               pulse 0.004 100000 `SigP.append`
-               pulse 0.005 200000 `SigP.append`
-               pulse 0.006 400000))
-
-
-triggerLFO :: SigP.T p (Value Float)
-triggerLFO =
-   SigP.osciSimple Wave.approxSine2 0 (pure (0.00015 :: Float))
-   +
-   SigP.osciSimple Wave.approxSine2 0 (pure (0.000037 :: Float))
-
-trackZeros :: CausalP.T p (Value Float) (Value Bool)
-trackZeros =
-   CausalV.zipWith (\x y -> x %&& Value.not y) .
-   (id &&& CausalP.delay1 (pure False)) .
-   CausalV.map (%> 0)
-
-fmPingSig :: Param.T p Float -> Param.T p Float -> SigP.T p (Value Float)
-fmPingSig freq depth =
-   SigP.envelope
-      (Sig.exponential2 5000 1)
-      ((CausalP.osciSimple Wave.approxSine2 $> SigP.constant freq)
-       $*
-       (SigP.constant depth * SigP.osciSimple Wave.approxSine2 0 (2*freq)))
-
-sweepTrigger :: IO ()
-sweepTrigger =
-   SVL.writeFile "speedtest.f32" . asMono .
-         (\f -> f SVL.defaultChunkSize (0.01 :: Float)) =<<
-      SigP.runChunky
-         (Sig.zipWith (flip Maybe.select) (SigP.noise 0 0.01) $
-            (CausalP.trigger (const $ fmPingSig (pure (0.005 :: Float))) $*
-               liftA2 Maybe.fromBool
-                  (CausalP.take 10000000 . trackZeros $* triggerLFO)
-                  (5 * SigP.osciSimple Wave.approxSine2 0 (pure (0.00001 :: Float)))))
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts #-}
+module Main where
+
+import Synthesizer.LLVM.LAC2011 ()
+import Synthesizer.LLVM.ExampleUtility
+
+import qualified Synthesizer.LLVM.Server.Default as Default
+import qualified Synthesizer.LLVM.Server.SampledSound as Sample
+
+import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as BandPass
+import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
+import qualified Synthesizer.LLVM.Filter.Butterworth as Butterworth
+import qualified Synthesizer.LLVM.Filter.Chebyshev as Chebyshev
+import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1
+import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2
+import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as Filt2P
+import qualified Synthesizer.LLVM.Filter.Moog as Moog
+import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
+import qualified Synthesizer.LLVM.Filter.NonRecursive as FiltNR
+import qualified Synthesizer.LLVM.Causal.Helix as Helix
+import qualified Synthesizer.LLVM.Causal.ControlledPacked as CtrlPS
+import qualified Synthesizer.LLVM.Causal.Controlled as Ctrl
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Causal.Functional as Func
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Core as SigCore
+import qualified Synthesizer.LLVM.Generator.Source as Source
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Interpolation as Interpolation
+import qualified Synthesizer.LLVM.Storable.Signal as SigStL
+import qualified Synthesizer.LLVM.ConstantPiece as Const
+import qualified Synthesizer.LLVM.Wave as Wave
+import Synthesizer.LLVM.Causal.Functional (($&), (&|&))
+import Synthesizer.LLVM.Causal.Process (($<), ($>), ($*), ($<#), ($*#))
+
+import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+
+import qualified LLVM.DSL.Expression.Maybe as ExprMaybe
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp, (>*), (&&*))
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Vector.Instance as MultiVectorI
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.Maybe as Maybe
+
+import qualified LLVM.Core as LLVM
+import LLVM.Util.Arithmetic () -- Floating instance for TValue
+
+import qualified Type.Data.Num.Decimal as TypeNum
+import Type.Data.Num.Decimal (D2, D4, (:*:))
+import Type.Base.Proxy (Proxy)
+
+import qualified Synthesizer.CausalIO.Process as PIO
+import qualified Synthesizer.Causal.Class as CausalClass
+import qualified Synthesizer.Zip as Zip
+import qualified Synthesizer.State.Control as CtrlS
+import qualified Synthesizer.State.Signal as SigS
+
+import qualified Synthesizer.Plain.Filter.Recursive as FiltR
+import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1Core
+
+import Control.Arrow (Arrow, arr, first, (&&&), (^<<), (<<^), (***))
+import Control.Category ((<<<), (.), id)
+import Control.Applicative (liftA2)
+import Control.Functor.HT (void)
+import Control.Monad (when, join)
+
+import qualified Data.StorableVector.Lazy as SVL
+import qualified Data.StorableVector as SV
+import Foreign.Storable (Storable)
+
+import qualified Data.EventList.Relative.TimeBody  as EventList
+import qualified Data.EventList.Relative.BodyTime  as EventListBT
+import qualified Data.EventList.Relative.MixedTime as EventListMT
+import qualified Data.EventList.Relative.TimeMixed as EventListTM
+import qualified Numeric.NonNegative.Wrapper as NonNeg
+
+import qualified Sound.Sox.Option.Format as SoxOption
+import qualified Sound.Sox.Play as SoxPlay
+-- import qualified Synthesizer.ALSA.Storable.Play as Play
+
+import qualified Data.NonEmpty.Class as NonEmptyC
+import qualified Data.NonEmpty as NonEmpty
+import qualified Data.Foldable as Fold
+import Data.Function.HT (nest)
+import Data.NonEmpty ((!:))
+import Data.Semigroup ((<>))
+import Data.Traversable (sequenceA)
+import Data.Tuple.HT (mapSnd)
+import System.Path ((</>))
+import System.Random (randomRs, mkStdGen)
+
+import qualified System.Unsafe as Unsafe
+import qualified System.IO as IO
+import Control.Exception (bracket)
+
+import qualified Algebra.Field as Field
+
+import qualified NumericPrelude.Numeric as NP
+import qualified Prelude as P
+import NumericPrelude.Numeric (fromIntegral, sum, (+), (-), (/), (*))
+import Prelude hiding (fst, snd, id, (.), fromIntegral, sum, (+), (-), (/), (*))
+
+
+asStereoPacked :: Id (vector (Serial.T D4 (Stereo.T Float)))
+asStereoPacked = id
+
+asStereoInterleaved :: Id (vector (StereoInt.T D4 Float))
+asStereoInterleaved = id
+
+
+{- |
+> playStereo (Sig.amplifyStereo 0.3 $ stereoOsciSaw 0.01)
+-}
+playStereo :: Sig.T (Stereo.T (MultiValue.T Float)) -> IO ()
+playStereo sig =
+   playStereoVector . ($ SVL.chunkSize 100000) =<<
+   Render.run (Stereo.multiValue <$> sig)
+
+playStereoVector :: SVL.Vector (Stereo.T Float) -> IO ()
+playStereoVector =
+   void . SoxPlay.simple SVL.hPut SoxOption.none 44100
+
+playMono :: Sig.MV Float -> IO ()
+playMono sig  =  playMonoVector . ($ SVL.chunkSize 100000) =<< Render.run sig
+
+playMonoVector :: SVL.Vector Float -> IO ()
+playMonoVector =
+   void . SoxPlay.simple SVL.hPut SoxOption.none 44100
+
+
+playFileMono :: FilePath -> IO ()
+playFileMono fileName = do
+   f <- Render.run id
+   IO.withFile fileName IO.ReadMode $ \h ->
+      playStereoVector . f (SVL.chunkSize 100000) .
+      asStereo . snd
+       =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h
+
+
+frequency :: Float -> Exp Float
+frequency = Expr.cons
+
+{- |
+Assist GHC-7.10.3 with determining the type of causal processes.
+GHC-7.8.4 and GHC-8.0.1 do not need it.
+-}
+causalP :: Causal.T a b -> Causal.T a b
+causalP = id
+
+
+constant :: Float -> IO ()
+constant y =
+   (SV.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ 1000) $ Render.run $
+   Sig.constant (Expr.cons y)
+
+saw :: IO ()
+saw =
+   (SV.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ 10000000) $ Render.run $
+   Sig.osci Wave.saw 0 0.01
+
+exponential :: IO ()
+exponential =
+   (SV.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ 10000000) $ Render.run $
+   Sig.exponential2 50000 1
+
+triangle :: IO ()
+triangle =
+   (SV.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ 10000000) $ Render.run $
+   Sig.osci Wave.triangle 0.25 0.01
+
+trianglePack :: IO ()
+trianglePack =
+   (SV.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap ($ div 10000000 4) $ Render.run $
+   (Causal.map (Expr.liftM Wave.triangle) $*) $
+   SigPS.packSmall $
+   SigCore.osci 0.25 (4.015803e-4)
+
+trianglePacked :: IO ()
+trianglePacked =
+   (SV.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap ($ div 10000000 4) $ Render.run $
+   (CausalPS.osci Wave.triangle
+     $< SigPS.constant 0.25
+     $* SigPS.constant 0.01)
+
+triangleReplicate :: IO ()
+triangleReplicate =
+   (SV.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap ($ div 10000000 4) $ Render.run $
+   (CausalPS.shapeModOsci
+       (\k p -> do
+           x <- Wave.triangle =<< Wave.replicate k p
+           y <- Wave.approxSine4 =<< Wave.halfEnvelope p
+           A.mul x y)
+     $< SigPS.rampInf 1000000
+     $< SigPS.constant 0
+     $* SigPS.constant 0.01)
+
+rationalSine :: IO ()
+rationalSine =
+   (SV.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap ($ div 10000000 4) $ Render.run $
+   (CausalPS.shapeModOsci Wave.rationalApproxSine1
+     $< (0.001 + SigPS.rampInf 10000000)
+     $< SigPS.constant 0
+     $* SigPS.constant 0.01)
+
+rationalSineStereo :: IO ()
+rationalSineStereo =
+   (SV.writeFile "speedtest.f32" . asStereoPacked =<<) $
+   fmap ($ div 10000000 4) $ Render.run $
+   fmap Stereo.multiValueSerial $
+   liftA2 Stereo.cons
+      (CausalPS.shapeModOsci Wave.rationalApproxSine1
+        $< (0.001 + SigPS.rampInf 10000000)
+        $< SigPS.constant (-0.25)
+        $* SigPS.constant 0.00999)
+      (CausalPS.shapeModOsci Wave.rationalApproxSine1
+        $< (0.001 + SigPS.rampInf 10000000)
+        $< SigPS.constant 0.25
+        $* SigPS.constant 0.01001)
+
+
+pingSig :: Float -> Sig.MV Float
+pingSig freq =
+   Sig.exponential2 50000 1
+   *
+   Sig.osci Wave.saw 0.5 (Expr.cons freq)
+
+pingSigP :: Exp Float -> Sig.MV Float
+pingSigP freq =
+   Sig.exponential2 50000 1
+   *
+   Sig.osci Wave.saw 0.5 freq
+
+ping :: IO ()
+ping =
+   (SV.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ 10000000) $ Render.run $
+   pingSig 0.01
+
+pingSigPacked :: Exp Float -> Sig.T (CausalPS.Serial D4 Float)
+pingSigPacked freq =
+   SigPS.exponential2 50000 1
+   *
+   SigPS.osci Wave.saw 0 freq
+
+pingPacked :: IO ()
+pingPacked =
+   (SV.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap (\f -> f (div 10000000 4) (0.01::Float)) $ Render.run $
+   pingSigPacked
+
+pingUnpack :: IO ()
+pingUnpack =
+   (SV.writeFile "speedtest.f32" . asMono =<<) $
+   fmap (\f -> f 10000000 (0.01::Float)) $ Render.run $
+   SigPS.unpack . pingSigPacked
+
+pingSmooth :: IO ()
+pingSmooth =
+   SV.writeFile "speedtest-scalar.f32" . asMono . ($ 10000000) =<<
+   Render.run
+      (Filt1.lowpassCausal
+         $< fmap Filt1Core.Parameter (1 - Sig.exponential2 50000 1)
+         $* Sig.osci Wave.triangle 0 0.01)
+
+pingSmoothPacked :: IO ()
+pingSmoothPacked =
+   SV.writeFile "speedtest-vector.f32" . asMonoPacked . ($ div 10000000 4) =<<
+   Render.run
+      (Filt1.lowpassCausalPacked
+         $< fmap Filt1Core.Parameter (1 - Sig.exponential2 (50000/4) 1)
+         $* SigPS.osci Wave.triangle 0 0.01)
+
+stereoOsciSaw :: Exp Float -> Sig.T (Stereo.T (MultiValue.T Float))
+stereoOsciSaw freq =
+   liftA2 Stereo.cons
+      (Sig.osci Wave.saw 0.0 (freq*1.001) +
+       Sig.osci Wave.saw 0.2 (freq*1.003) +
+       Sig.osci Wave.saw 0.1 (freq*0.995))
+      (Sig.osci Wave.saw 0.1 (freq*1.005) +
+       Sig.osci Wave.saw 0.7 (freq*0.997) +
+       Sig.osci Wave.saw 0.5 (freq*0.999))
+
+stereoOsciSawPacked :: Float -> Sig.T (Stereo.T (MultiValue.T Float))
+stereoOsciSawPacked freq =
+   let mix4 = Expr.liftM $ MultiVector.sum . MultiVectorI.fromMultiValue
+   in  liftA2 Stereo.cons
+          ((Causal.map mix4 $*) $
+           Sig.osci Wave.saw
+              (Expr.cons $ LLVM.consVector 0.0 0.2 0.1 0.4)
+              (Expr.cons $ fmap (freq*) $
+               LLVM.consVector 1.001 1.003 0.995 0.996))
+          ((Causal.map mix4 $*) $
+           Sig.osci Wave.saw
+              (Expr.cons $ LLVM.consVector 0.1 0.7 0.5 0.7)
+              (Expr.cons $ fmap (freq*) $
+               LLVM.consVector 1.005 0.997 0.999 1.001))
+
+stereoDeinterleave :: NonEmpty.T [] a -> NonEmpty.T [] (Stereo.T a)
+stereoDeinterleave xt =
+   case xt of
+      NonEmpty.Cons _ [] -> error "stereoDeinterleave: singleton"
+      NonEmpty.Cons x0 (x1:xs) ->
+         Stereo.cons x0 x1 !:
+            let go (y0:y1:ys) = Stereo.cons y0 y1 : go ys
+                go [] = []
+                go [_] = error "stereoDeinterleave: odd length"
+            in go xs
+
+mixVectorToStereo ::
+   (TypeNum.Positive n, MultiVector.Additive a) =>
+   MultiVector.T n a -> LLVM.CodeGenFunction r (Stereo.T (MultiValue.T a))
+mixVectorToStereo =
+   NonEmpty.foldBalanced (\x y -> join $ liftA2 A.add x y) .
+   fmap sequenceA . stereoDeinterleave . MultiVector.dissectList1
+
+mixVec ::
+   (TypeNum.Positive n, MultiVector.Additive a) =>
+   Exp (LLVM.Vector n a) -> Stereo.T (Exp a)
+mixVec =
+   Stereo.unExpression .
+   Expr.liftM
+      (fmap Stereo.multiValue . mixVectorToStereo . MultiVectorI.fromMultiValue)
+
+stereoOsciSawPacked2 :: Float -> Sig.T (Stereo.T (MultiValue.T Float))
+stereoOsciSawPacked2 freq =
+   (Causal.map mixVec $*) $
+   Sig.osci (Wave.trapezoidSlope (A.fromRational' 5))
+      (Expr.cons $ LLVM.consVector 0.0 0.2 0.1 0.4 0.1 0.7 0.5 0.7)
+      (Expr.cons $ fmap (freq*) $
+       LLVM.consVector 1.001 1.003 0.995 0.996 1.005 0.997 0.999 1.001)
+
+stereo :: IO ()
+stereo =
+   SV.writeFile "speedtest.f32" . asStereo .  ($ 10000000) =<<
+   Render.run
+      (Stereo.multiValue <$> Causal.amplifyStereo 0.25
+         $* stereoOsciSawPacked2 0.01)
+
+lazy :: IO ()
+lazy =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run {- SVL.defaultChunkSize - too slow -}
+      (Causal.envelope
+         $< Sig.exponential2 50000 1
+         $* Sig.osci Wave.sine 0.5 0.01)
+
+lazyStereo :: IO ()
+lazyStereo =
+   (SVL.writeFile "speedtest.f32" . asStereo . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (Stereo.multiValue <$> Causal.amplifyStereo 0.25
+         $* stereoOsciSawPacked 0.01)
+
+packTake :: IO ()
+packTake =
+   (SVL.writeFile "speedtest.f32" . asMonoPacked . ($ SVL.chunkSize 1000) =<<) $
+   (Render.run . SigPS.packRotate)
+      (Causal.take 5 $* Sig.osci Wave.saw 0 (frequency 0.01))
+
+chord :: Float -> Sig.T (Stereo.T (MultiValue.T Float))
+chord base =
+   {-
+   This exceeds available vector registers
+   and thus needs more stack accesses.
+   Thus it needs twice as much time as the simple mixing.
+   However doing all 32 oscillators in parallel
+   and mix them in one go might be still faster.
+
+   foldl1 (Sig.zipWith Frame.mixStereoV) $
+   -}
+   NonEmpty.foldBalanced (+) $
+   fmap (\f -> stereoOsciSawPacked2 (base*f)) $
+   0.25 !: 1.00 : 1.25 : 1.50 : []
+
+lazyChord :: IO ()
+lazyChord =
+   (SVL.writeFile "speedtest.f32" . asStereo . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run (Stereo.multiValue <$> Causal.amplifyStereo 0.1 $* chord 0.005)
+
+filterSweepComplex :: IO ()
+filterSweepComplex =
+   playStereo $
+      (Causal.amplifyStereo 0.3 . BandPass.causal
+         $< (Causal.map (\x -> BandPass.parameter 100 (0.01 * exp (2*x))) $*
+             Sig.osci Wave.sine 0 (0.1/44100))
+         $* chord 0.005)
+
+lfoSineCausal ::
+   Causal.T (MultiValue.T Float) a -> Exp Float -> Sig.T a
+lfoSineCausal f reduct =
+   f . Causal.map (\x -> 0.01 * exp (2*x)) $*
+   Sig.osci Wave.sine 0 (reduct * 0.1/44100)
+
+lfoSine ::
+   (Expr.Aggregate ae a) =>
+   (Exp Float -> ae) ->
+   Exp Float -> Sig.T a
+lfoSine f = lfoSineCausal (Causal.map f)
+
+filterSweep :: IO ()
+filterSweep =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 10000) $
+   Render.run $
+      (0.2 * Ctrl.processCtrlRate 128 (lfoSine (Filt2.bandpassParameter 100))
+         $* Sig.osci Wave.saw 0 (frequency 0.01))
+
+filterSweepPacked :: IO ()
+filterSweepPacked =
+   (SVL.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap (SVL.take (div 10000000 4)) $
+   fmap ($ SVL.chunkSize 10000) $
+   Render.run
+      (0.2 *
+       CtrlPS.processCtrlRate 128 (lfoSine (Filt2.bandpassParameter 100))
+            $* SigPS.osci Wave.saw 0 (frequency 0.01))
+
+exponentialFilter2Packed :: IO ()
+exponentialFilter2Packed =
+   (SVL.writeFile "speedtest.f32" . asMonoPacked16 =<<) $
+   fmap (SVL.take (div 10000000 16)) $
+   fmap ($ SVL.chunkSize 10000) $
+   Render.run
+      (Filt2.causalPacked
+         $< Sig.constant (Filt2.Parameter 1 0 0   0 0.99)
+         $* (
+--             (Causal.delay1 $ Serial.fromFixedList (0.1 !: 0.01 !: 0.001 !: 0.0001 !: Empty.Cons))
+--             (Causal.delay1 $ Serial.replicate 1)
+             (Causal.delay1 $ Serial.fromFixedList (1 !: NonEmptyC.repeat 0))
+               $* 0))
+
+filterSweepPacked2 :: IO ()
+filterSweepPacked2 =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 10000) $
+   Render.run
+      (0.2 *
+       Ctrl.processCtrlRate 128 (lfoSine (Filt2P.bandpassParameter 100))
+         $* Sig.osci Wave.saw 0 (frequency 0.01))
+
+butterworthNoisePacked :: IO ()
+butterworthNoisePacked =
+   (SVL.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap (SVL.take (div 10000000 4)) $
+   fmap ($ SVL.chunkSize 10000) $
+   Render.run
+      (CausalPS.amplify 0.2 .
+       CtrlPS.processCtrlRate 128
+         (lfoSineCausal
+            (Butterworth.parameterCausal TypeNum.d3 FiltR.Lowpass $<# 0.5))
+         $* SigPS.noise 0 0.3)
+
+chebyshevNoisePacked :: IO ()
+chebyshevNoisePacked =
+   (SVL.writeFile "speedtest.f32" . asMonoPacked =<<) $
+   fmap (SVL.take (div 10000000 4)) $
+   fmap ($ SVL.chunkSize 10000) $
+   Render.run
+      (CausalPS.amplify 0.2 .
+       CtrlPS.processCtrlRate 128
+         (lfoSineCausal
+            (Chebyshev.parameterCausalA TypeNum.d5 FiltR.Lowpass $<# 0.5))
+         $* SigPS.noise 0 0.3)
+
+
+upsample :: IO ()
+upsample =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (let reduct = 128 :: Exp Float
+       in Sig.interpolateConstant reduct
+            (Sig.osci Wave.sine 0 (reduct*0.1/44100)))
+
+
+filterSweepControlRateCausal ::
+   Causal.T
+      (Stereo.T (MultiValue.T Float))
+      (Stereo.T (MultiValue.T Float))
+filterSweepControlRateCausal =
+   Causal.amplifyStereo 0.3 <<< BandPass.causal
+   $< (let reduct = 128 :: Exp Float
+       in Sig.interpolateConstant reduct
+            (Causal.map (BandPass.parameter 100) .
+             Causal.map (\x -> 0.01 * exp (2*x))
+               $* Sig.osci Wave.sine 0 (reduct*0.1/44100)))
+
+{- |
+Trigonometric functions are very slow in LLVM
+because they are translated to calls to C's math library.
+Thus it is advantageous to compute filter parameters
+at a lower rate and interpolate constantly.
+-}
+filterSweepControlRate :: IO ()
+filterSweepControlRate =
+   (SVL.writeFile "speedtest.f32" . asStereo . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (Stereo.multiValue <$> filterSweepControlRateCausal $* chord 0.005)
+
+
+filterSweepMusic :: IO ()
+filterSweepMusic = do
+   proc <-
+      Render.run $ \music ->
+         Stereo.multiValue ^<< Causal.amplifyStereo 20 .
+            filterSweepControlRateCausal <<^ Stereo.unMultiValue $* music
+   music <- SV.readFile "lichter.f32"
+   SVL.writeFile "speedtest.f32" . asStereo
+      =<< proc (SVL.chunkSize 100000) music
+
+
+playFilterSweepMusicLazy :: IO ()
+playFilterSweepMusicLazy = do
+   proc <-
+      Render.run $ \vol music ->
+         Stereo.multiValue ^<< Causal.amplifyStereo vol .
+            filterSweepControlRateCausal <<^ Stereo.unMultiValue $* music
+   IO.withFile "lichter.f32" IO.ReadMode $ \h ->
+      playStereoVector . proc (SVL.chunkSize 100000) (20::Float) {-1.125-} . snd
+         =<< SVL.hGetContentsAsync (SVL.chunkSize 4321) h
+
+playFilterSweepMusicCausal :: IO ()
+playFilterSweepMusicCausal = do
+   proc <-
+      CausalRender.run $
+         Stereo.multiValue ^<< Causal.amplifyStereo 20 .
+            filterSweepControlRateCausal <<^ Stereo.unMultiValue
+   music <- SV.readFile "lichter.f32"
+   void $ SoxPlay.simple SV.hPut SoxOption.none 44100 =<<
+      pioApplyStrict proc music
+
+playFilterSweepMusicCausalLazy :: IO ()
+playFilterSweepMusicCausalLazy = do
+   proc <-
+      CausalRender.run $
+         Stereo.multiValue ^<< Causal.amplifyStereo 20 .
+            filterSweepControlRateCausal <<^ Stereo.unMultiValue
+   IO.withFile "lichter.f32" IO.ReadMode $ \h ->
+      playStereoVector =<< pioApply proc . snd
+       =<< SVL.hGetContentsAsync (SVL.chunkSize 43210) h
+
+
+deinterleaveProc ::
+   IO (Float ->
+       PIO.T
+         (SV.Vector (StereoInt.T D4 Float))
+         (Zip.T
+            (SV.Vector (StereoInt.T D4 Float))
+            (SV.Vector (StereoInt.T D4 Float))))
+deinterleaveProc =
+   CausalRender.run deinterleaveCausal
+
+deinterleaveCausal ::
+   Exp Float ->
+   Causal.T
+      (StereoInt.Value D4 Float)
+      (StereoInt.Value D4 Float, StereoInt.Value D4 Float)
+deinterleaveCausal freq =
+   Func.withArgs $ \input ->
+      let env =
+             Func.fromSignal $
+                0.5 * (1 + SigPS.osci (Wave.triangleSquarePower 4) 0 freq)
+      in  (Causal.zipWith StereoInt.envelope $& env &|& input)
+          &|&
+          (Causal.zipWith StereoInt.envelope $& (1-env) &|& input)
+
+deinterleave :: IO ()
+deinterleave = do
+   proc <- deinterleaveProc
+   runSplitProcess (proc (2/44100))
+
+
+disturbProc, disturbFMProc ::
+   IO (PIO.T
+         (SV.Vector (StereoInt.T D4 Float))
+         (Zip.T
+            (SV.Vector (StereoInt.T D4 Float))
+            (SV.Vector (StereoInt.T D4 Float))))
+disturbProc =
+   CausalRender.run $ crossMix disturbCausal
+
+disturbCausal, disturbFMCausal ::
+   Causal.T (StereoInt.Value D4 Float) (StereoInt.Value D4 Float)
+disturbCausal =
+   Func.withArgs $ \inputInt ->
+      let tone = Func.fromSignal $ SigPS.osci Wave.triangle 0 (440/44100)
+          getEnvelope x =
+             Filt1.lowpassCausalPacked $&
+                (Func.fromSignal $
+                 Sig.constant $ Filt1Core.parameter (1/44100))
+                &|&
+                (Causal.map abs $& x)
+          envelopedTone x = getEnvelope x * tone
+      in  Causal.map StereoInt.interleave $&
+          CausalPS.amplifyStereo 5 $&
+          Stereo.liftApplicative envelopedTone
+             (Causal.map StereoInt.deinterleave $& inputInt)
+
+disturbFMProc =
+   CausalRender.run $ crossMix disturbFMCausal
+
+disturbFMCausal =
+   Func.withArgs $ \inputInt ->
+      let getEnvelope x =
+             Filt1.lowpassCausalPacked $&
+                (Func.fromSignal $
+                 Sig.constant $ Filt1Core.parameter (1/44100))
+                &|&
+                (Causal.map abs $& x)
+          modulatedTone x =
+             getEnvelope x *
+             (CausalPS.osci Wave.triangle $&
+                NP.zero
+                &|&
+                10 * getEnvelope (CausalPS.differentiate 0 $& x))
+      in  Causal.map StereoInt.interleave $&
+          CausalPS.amplifyStereo 5 $&
+          Stereo.liftApplicative modulatedTone
+             (Causal.map StereoInt.deinterleave $& inputInt)
+
+disturb :: IO ()
+disturb =
+   runSplitProcess =<< disturbFMProc
+
+
+wowFlutterProc ::
+   IO (PIO.T
+         (SV.Vector (StereoInt.T D4 Float))
+         (Zip.T
+            (SV.Vector (StereoInt.T D4 Float))
+            (SV.Vector (StereoInt.T D4 Float))))
+wowFlutterProc =
+   CausalRender.run $ crossMix wowFlutterCausal
+
+wowFlutterCausal ::
+   Causal.T (StereoInt.Value D4 Float) (StereoInt.Value D4 Float)
+wowFlutterCausal =
+   Func.withArgs $ \inputInt ->
+      let freq =
+             Func.fromSignal $ (44100*) $
+                0.01 * (1 + SigPS.osci Wave.triangle 0 (1/44100 :: Exp Float)) +
+                0.01 * (1 + SigPS.osci Wave.approxSine2
+                                                  0 (1.23/44100 :: Exp Float))
+          modulatedTone x =
+             CausalPS.pack
+                (Causal.delayControlledInterpolated Interpolation.linear
+                    (0 :: Exp Float) (441*2*2+10))
+             $&
+             freq &|& x
+      in  Causal.map StereoInt.interleave $&
+          Stereo.liftApplicative modulatedTone
+             (Causal.map StereoInt.deinterleave $& inputInt)
+
+crossMix ::
+   Causal.T (StereoInt.Value D4 Float) (StereoInt.Value D4 Float) ->
+   Causal.T
+      (StereoInt.Value D4 Float)
+      (StereoInt.Value D4 Float, StereoInt.Value D4 Float)
+crossMix proc =
+   ((fst NP.+ snd)  &&&  (fst NP.- snd))
+   .
+   (id &&& proc)
+   .
+   Causal.map (StereoInt.amplify 0.5)
+
+
+wowFlutter :: IO ()
+wowFlutter =
+   runSplitProcess =<< wowFlutterProc
+
+
+
+scrambleProc0, scrambleProc1 ::
+   IO (Float ->
+       PIO.T
+         (SV.Vector (StereoInt.T D4 Float))
+         (Zip.T
+            (SV.Vector (StereoInt.T D4 Float))
+            (SV.Vector (StereoInt.T D4 Float))))
+scrambleProc0 =
+   CausalRender.run $ \freq ->
+      deinterleaveCausal freq NP.+
+      (id &&& NP.negate id) .
+         Causal.map (StereoInt.amplify 0.5) . wowFlutterCausal
+
+scrambleProc1 =
+   CausalRender.run $ \freq ->
+      deinterleaveCausal freq NP.+
+      (id &&& NP.negate id) .
+         Causal.map (StereoInt.amplify 0.3) .
+         (wowFlutterCausal NP.+ disturbFMCausal)
+
+scramble :: IO ()
+scramble = do
+   proc <- scrambleProc1
+   runSplitProcess (proc (2/44100))
+
+
+runSplitProcess ::
+   (Storable a) =>
+   PIO.T (SV.Vector a) (Zip.T (SV.Vector a) (SV.Vector a)) ->
+   IO ()
+runSplitProcess proc = do
+   void $
+      IO.withFile "/tmp/test.f32" IO.ReadMode $ \h ->
+      IO.withFile "/tmp/even.f32" IO.WriteMode $ \h0 ->
+      IO.withFile "/tmp/odd.f32"  IO.WriteMode $ \h1 ->
+
+      case proc of
+         PIO.Cons next create delete ->
+            {-
+            Is the use of 'bracket' correct?
+            I think 'delete' must be called with the final state,
+            not with the initial one.
+            -}
+            bracket create delete $
+               let chunkSize = 543210
+                   loop s0 = do
+                      chunk <- SV.hGet h chunkSize
+                      (Zip.Cons y0 y1, s1) <- next chunk s0
+                      SV.hPut h0 y0
+                      SV.hPut h1 y1
+                      when
+                         (SV.length y0 >= SV.length chunk &&
+                          SV.length y1 >= SV.length chunk &&
+                          SV.length chunk >= chunkSize)
+                         (loop s1)
+               in  loop
+
+
+antimixProc ::
+   IO (SVL.Vector (StereoInt.T D4 Float) ->
+       PIO.T
+         (SV.Vector (StereoInt.T D4 Float))
+         (Zip.T
+            (SV.Vector (StereoInt.T D4 Float))
+            (SV.Vector (StereoInt.T D4 Float))))
+antimixProc =
+   CausalRender.run $ \xs -> crossMix $
+      Causal.map (StereoInt.amplify 0.5) . Causal.fromSignal xs
+
+antimix :: IO ()
+antimix = do
+   proc <- antimixProc
+   void $
+      IO.withFile "/tmp/test.f32" IO.ReadMode $ \h ->
+      IO.withFile "/tmp/even.f32" IO.WriteMode $ \h0 ->
+      IO.withFile "/tmp/odd.f32"  IO.WriteMode $ \h1 -> do
+         let chunkSize = SVL.chunkSize 543210
+         input <- fmap snd $ SVL.hGetContentsAsync chunkSize h
+         let vectorSize = 4
+             additive = SVL.drop (div 44100 vectorSize) input
+{-
+             additive =
+                case SVL.splitAt (div 44100 vectorSize) input of
+                   (prefix, suffix) ->
+                      SVL.append suffix $
+                      SVL.replicate chunkSize (SVL.length prefix) StereoInt.zero
+-}
+{-
+             additive =
+                case SVL.splitAt (div 44100 vectorSize) input of
+                   (prefix, suffix) -> SVL.append suffix prefix
+-}
+
+         case proc additive of
+            PIO.Cons next create delete ->
+               {-
+               Is the use of 'bracket' correct?
+               I think 'delete' must be called with the final state,
+               not with the initial one.
+               -}
+               bracket create delete $ \state ->
+                  let loop cs0 s0 =
+                         case cs0 of
+                            [] -> return ()
+                            c : cs -> do
+                               (Zip.Cons y0 y1, s1) <- next c s0
+                               SV.hPut h0 y0
+                               SV.hPut h1 y1
+                               when
+                                  (SV.length y0 >= SV.length c &&
+                                   SV.length y1 >= SV.length c)
+                                  (loop cs s1)
+                  in  loop (SVL.chunks input) state
+
+
+arrangeLazy :: IO ()
+arrangeLazy = do
+   IO.hSetBuffering IO.stdout IO.NoBuffering
+   arrange <- SigStL.makeArranger
+   print $
+      arrange (SVL.chunkSize 2) $
+      EventList.fromPairList $
+         (0, SVL.pack (SVL.chunkSize 2) [1,2::Double]) :
+         (0, SVL.pack (SVL.chunkSize 2) [3,4,5,6]) :
+         (2, SVL.pack (SVL.chunkSize 2) [7,8,9,10]) :
+ --        repeat (2, SVL.empty)
+--         (2, SVL.empty) :
+--         (2, SVL.empty) :
+--         (2::NonNeg.Int, error "undefined sound") :
+         error "end of list"
+ --        []
+
+
+{- |
+This is inefficient because pingSig is compiled by LLVM
+for every occurence of the sound!
+
+randomTones :: IO ()
+randomTones = do
+   playMonoVector $
+      SigStL.arrange (SVL.chunkSize 12345) $
+      EventList.fromPairList $ zip
+         (cycle $ map (flip div 16 . (44100*)) [1,2,3])
+         (cycle $ map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 54321) .
+                       pingSig . (0.01*))
+          [1,1.25,1.5,2])
+-}
+
+{-
+{- |
+So far we have not managed to compile signals
+that depend on parameters.
+Thus in order to avoid much recompilation,
+we compile and render a few sounds in advance.
+-}
+pingTones :: [SVL.Vector Float]
+pingTones =
+   map (SVL.take 44100 . Sig.renderChunky (SVL.chunkSize 4321) .
+        pingSig . (0.01*))
+   [1,1.25,1.5,2]
+-}
+
+pingTonesIO :: IO [SVL.Vector Float]
+pingTonesIO =
+   fmap
+      (\pingVec ->
+         map
+            (SVL.take 44100 .
+             pingVec (SVL.chunkSize 4321) .
+             (0.01*))
+            [1,1.25,1.5,2::Float])
+      (Render.run pingSigP)
+
+{-
+Arrange itself does not seem to have a space leak with temporary data.
+However it may leak sound data.
+This is not very likely because this would result in a large memory leak.
+
+Generate random tones in order to see whether generated sounds leak.
+How does 'arrange' compare with 'concat'?
+-}
+
+{-
+cycleTones :: IO ()
+cycleTones = do
+--   playMono $
+   pings <- pingTonesIO
+   SVL.writeFile "test.f32" $
+--   Play.auto (0.01::Double) 44100 $
+      asMono $
+{-
+after 13min runtime memory consumption increased from 2.5 to 3.9
+and we get lot of buffer underruns with this implementation of amplification
+(renderChunky . amplify . fromStorableVector)
+-}
+      Sig.renderChunky (SVL.chunkSize 432109) $
+      Sig.amplify 0.1 $
+      Sig.fromStorableVectorLazy $
+{-
+after 20min memory consumption increased from 2.5 to 3.4
+and we get lot of buffer underruns with applyStorableChunky
+-}
+{-
+applyStorableChunky applied to concatenated zero vectors
+starts with memory consumption 1.0 and after an hour, it's still 1.1
+without buffer underruns.
+-}
+{-
+      CausalP.applyStorableChunky (CausalP.amplify $# (0.1::Float)) () $
+      asMono $
+-}
+{-
+with chunksize 12345678
+after 50min runtime the memory consumption increased from 12.0 to 26.2
+
+with chunksize 123
+after 25min runtime the memory consumption is constant 7.4
+however at start time there 5 buffer underruns, but no more
+probably due to initial LLVM compilation
+
+with chunksize 1234567 and SVL.replicate instead of pingTones
+we get memory consumption from 1.3 to 3.2 in 15min,
+while producing lots of buffer underruns.
+After 45min in total, it is still 3.2 of memory consumption.
+Is this a memory leak, or isn't it?
+
+with chunksize 12345678 and SVL.replicate
+we get from 5.6 to 10.2 in 3min
+to 14.9 after total 13min.
+-}
+{-
+      SigStL.arrange (SVL.chunkSize 12345678) $
+      EventList.fromPairList $ zip
+         (repeat (div 44100 8))
+--         (cycle $ map (flip div 4 . (44100*)) [1,2,3])
+-}
+{-
+With plain concatenation of those zero vectors
+we stay constantly at 0.4 memory consumption and no buffer underruns over 30min.
+-}
+      SVL.concat
+         (cycle pings)
+--         (repeat $ SVL.replicate (SVL.chunkSize 44100) 44100 0)
+   return ()
+-}
+
+
+tonesChunkSize :: SVL.ChunkSize
+numTones :: Int
+
+{-
+For one-time-compiled fill functions,
+larger chunks have no relevant effect on the processing speed.
+-}
+(tonesChunkSize, numTones) =
+   (SVL.chunkSize 441, 200)
+--   (SVL.chunkSize 44100, 200)
+
+fst :: Arrow arrow => arrow (a,b) a
+fst = arr P.fst
+
+snd :: Arrow arrow => arrow (a,b) b
+snd = arr P.snd
+
+
+{-# NOINLINE makePing #-}
+makePing :: IO (Float -> Float -> SVL.Vector Float)
+makePing =
+   fmap ($ tonesChunkSize) $
+   Render.run $ \halfLife freq ->
+      Causal.envelope
+         $< Sig.exponential2 halfLife 1
+         $* Sig.osci Wave.saw 0.5 freq
+
+tonesDown :: IO ()
+tonesDown = do
+   let dist = div 44100 10
+   pingp <- makePing
+   arrange <- SigStL.makeArranger
+   amplify <- CausalRender.run Causal.amplify
+   playMonoVector =<<
+      (pioApply (amplify (0.03::Float)) $
+       arrange tonesChunkSize $
+       EventList.fromPairList $
+       zip
+         (repeat (NonNeg.fromNumber dist))
+         (map (SVL.take (numTones * dist) . pingp 50000) $
+          iterate (0.999*) 0.01))
+
+
+vibes :: (Exp Float, Exp Float) -> Sig.MV Float
+vibes (modDepth, freq) =
+   let halfLife = 5000
+       -- sine = Wave.sine
+       sine = Wave.approxSine4
+   in Causal.envelope
+         $< Sig.exponential2 halfLife 1
+         $* (((Causal.osci sine
+                $< (Causal.envelope
+                       $< Sig.exponential2 halfLife modDepth
+                       $* (Causal.osci sine $* Sig.constant (0, 2*freq))))
+               <<<
+               Causal.amplify freq
+               <<<
+               (Causal.osci sine * 0.01 + 1))
+             $* Sig.constant (0, 0.0001))
+
+makeVibes :: IO ((Float,Float) -> SVL.Vector Float)
+makeVibes = fmap ($ tonesChunkSize) $ Render.run vibes
+
+vibesCycleVector :: ((Float,Float) -> SVL.Vector Float) -> IO (SVL.Vector Float)
+vibesCycleVector pingp =
+   (\evs -> fmap (\arrange -> arrange tonesChunkSize evs) SigStL.makeArranger) $
+   EventList.fromPairList $ zip
+      (repeat 5000)
+      (map (SVL.take 50000 . pingp) $
+       zip
+          (map (\k -> 0.5 * (1 - cos k)) $ iterate (0.05+) 0)
+          (cycle $ map (0.01*) [1, 1.25, 1.5, 2]))
+
+pioApply ::
+   (Storable a, Storable b) =>
+   PIO.T (SV.Vector a) (SV.Vector b) -> SVL.Vector a -> IO (SVL.Vector b)
+pioApply proc sig = do
+   act <- PIO.runStorableChunkyCont proc
+   return $ act (const SVL.empty) sig
+
+pioApplyStrict ::
+   (Storable a, Storable b) =>
+   PIO.T (SV.Vector a) (SV.Vector b) -> SV.Vector a -> IO (SV.Vector b)
+pioApplyStrict proc sig = do
+   act <- PIO.runCont proc
+   return $
+      case act (const []) [sig] of
+         chunk : _ -> chunk
+         [] -> SV.empty
+
+vibesCycle :: IO ()
+vibesCycle = do
+   sig <- vibesCycleVector =<< makeVibes
+   proc <- CausalRender.run Causal.amplify
+   playMonoVector =<< pioApply (proc (0.2::Float)) sig
+
+vibesEcho :: IO ()
+vibesEcho = do
+   sig <- vibesCycleVector =<< makeVibes
+   proc <-
+      CausalRender.run (\vol -> Causal.amplify vol <<< Causal.comb 0.5 7000)
+   playMonoVector =<< pioApply (proc (0.2::Float)) sig
+
+vibesReverb :: IO ()
+vibesReverb = do
+   sig <- vibesCycleVector =<< makeVibes
+   proc <-
+      CausalRender.run
+         (\params -> Causal.amplify 0.3 <<< Causal.reverbExplicit params)
+   playMonoVector =<<
+      pioApply
+         (proc (Causal.reverbParams (mkStdGen 142)
+                  TypeNum.d16 (0.9,0.97) (400,1000)))
+         sig
+
+vibesReverbStereo :: IO ()
+vibesReverbStereo = do
+   sig <- vibesCycleVector =<< makeVibes
+   proc <-
+      CausalRender.run
+         (\params ->
+            Stereo.multiValue
+            ^<<
+            Causal.amplifyStereo 0.3
+            <<<
+            Causal.stereoFromMonoParameterized Causal.reverbExplicit params
+            <<^
+            (\x -> Stereo.cons x x))
+   playStereoVector =<<
+      pioApply
+         (proc
+            (fmap
+                (\seed ->
+                   Causal.reverbParams (mkStdGen seed)
+                      TypeNum.d16 (0.9,0.97) (400,1000))
+                (Stereo.cons 142 857)))
+         sig
+
+
+stair :: IO ()
+stair =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap
+      (\f ->
+         f tonesChunkSize $
+         EventListBT.fromPairList $
+         zip (iterate (/2) 1) (iterate (2*) (1::NonNeg.Integer))) $
+   Render.run Const.flatten
+
+
+filterBass :: IO ()
+filterBass = do
+   proc <-
+      Render.run $ \xs ->
+         (fmap Stereo.multiValue BandPass.causal
+          <<<
+          CausalClass.feedSnd
+            (liftA2 Stereo.cons
+               (Sig.osci Wave.saw 0 (frequency 0.001499))
+               (Sig.osci Wave.saw 0 (frequency 0.001501)))
+          <<<
+          Causal.map (BandPass.parameter 100))
+         $*
+         Const.flatten xs
+
+   playStereoVector $ proc tonesChunkSize $
+      EventListBT.fromPairList $
+      zip
+         (map (((0.01::Float)*) . (2**) . (/12) . fromInteger) $
+          randomRs (0,24) (mkStdGen 998))
+         (repeat (6300::NonNeg.Int))
+
+
+mixVectorStereo ::
+   SVL.Vector (Stereo.T Float) ->
+   SVL.Vector (Stereo.T Float) ->
+   SVL.Vector (Stereo.T Float)
+mixVectorStereo = Unsafe.performIO mixVectorStereoIO
+
+mixVectorStereoIO ::
+   IO (SVL.Vector (Stereo.T Float) ->
+       SVL.Vector (Stereo.T Float) ->
+       SVL.Vector (Stereo.T Float))
+mixVectorStereoIO =
+   (\proc xs ys -> Unsafe.performIO $ pioApply (proc xs) ys)
+   <$>
+   CausalRender.run (\xs -> Causal.mix $< xs)
+
+{-
+slightly slower than mixVectorParam
+-}
+mixVectorHaskell :: SVL.Vector Float -> SVL.Vector Float -> SVL.Vector Float
+mixVectorHaskell = SVL.zipWith (+)
+
+toneMix :: IO ()
+toneMix = do
+   pingp <- makePing
+   mix <- CausalRender.run $ \x -> Causal.mix $< x
+   amplify <- CausalRender.run (Causal.amplify 0.1)
+   playMonoVector
+      =<< pioApply amplify
+      =<< ((\(x:xs) -> Fold.foldlM (pioApply . mix) x xs) $ take numTones $
+           map (pingp 1000000) $ iterate (*(2/3)) 0.01)
+
+fadeEnvelope :: Exp Word -> Exp Word -> Sig.MV Float
+fadeEnvelope intro len =
+   Sig.parabolaFadeIn intro
+   <>
+   (Causal.take len $* 1)
+   <>
+   Sig.parabolaFadeOut intro
+
+fadeEnvelopeWrite :: IO ()
+fadeEnvelopeWrite =
+   (SVL.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ SVL.chunkSize 1234) $
+   Render.run $ fadeEnvelope 100000 200000
+
+
+-- | normalize a list of numbers, such that they have a specific average
+-- Cf. haskore-supercollider/src/Haskore/Interface/SuperCollider/Example.hs
+normalizeLevel :: (Field.C a) => a -> [a] -> [a]
+normalizeLevel newAvrg xs =
+   let avrg = sum xs / fromIntegral (length xs)
+   in  map ((newAvrg-avrg)+) xs
+
+stereoOsciParams ::
+   (TypeNum.Integer n) =>
+   Proxy n -> Float -> (Float, Stereo.T (MultiValue.Array n (Float,Float)))
+stereoOsciParams np freq =
+   let n = TypeNum.integralFromProxy np
+       volume :: Float
+       volume = recip $ sqrt $ TypeNum.integralFromProxy np
+       detunes :: [Float]
+       detunes =
+          normalizeLevel 1 $ take (2*n) $
+             randomRs (0,0.03) $ mkStdGen 912
+       phases :: [Float]
+       phases = randomRs (0,1) $ mkStdGen 54
+   in (,) volume $
+      fmap MultiValue.Array $
+      uncurry Stereo.cons $ splitAt n $
+      zipWith
+         (\phase detune -> (phase, detune*freq))
+         phases detunes
+
+stereoOsciSawP ::
+   (TypeNum.Natural n) =>
+   (TypeNum.Natural arrSize, arrSize ~ (n :*: LLVM.UnknownSize)) =>
+   (TypeNum.Natural stereoSize, stereoSize ~ (D2 :*: arrSize)) =>
+   Exp Float -> Stereo.T (Exp (MultiValue.Array n (Float,Float))) ->
+   Sig.MV (Stereo.T Float)
+stereoOsciSawP volume =
+   fmap Stereo.multiValue
+   .
+   stereoFromMonoParameterizedSignal
+      (\params ->
+         Causal.amplify volume
+         $* multiMixSignal
+               (\phaseFreq ->
+                   Sig.osci Wave.saw
+                      (Expr.fst phaseFreq)
+                      (Expr.snd phaseFreq))
+               params)
+
+stereoFromMonoParameterizedSignal ::
+   (Marshal.C x) =>
+   (D2 :*: LLVM.SizeOf (Marshal.Struct x) ~ arrSize,
+    TypeNum.Natural arrSize) =>
+   (Exp x -> Sig.MV Float) ->
+   Stereo.T (Exp x) -> Sig.T (Stereo.T (MultiValue.T Float))
+stereoFromMonoParameterizedSignal f ps =
+   Causal.toSignal $
+      Causal.stereoFromMonoParameterized (Causal.fromSignal . f) ps
+      <<^
+      (\() -> Stereo.cons () ())
+
+multiMixSignal ::
+   (TypeNum.Natural n, Marshal.C x,
+    n :*: LLVM.SizeOf (Marshal.Struct x) ~ arraySize,
+    TypeNum.Natural arraySize,
+    Tuple.Undefined a, Tuple.Phi a, A.Additive a) =>
+   (Exp x -> Sig.T a) ->
+   Exp (MultiValue.Array n x) -> Sig.T a
+multiMixSignal f =
+   Causal.toSignal . multiMix (Causal.fromSignal . f)
+
+multiMix ::
+   (TypeNum.Natural n, Marshal.C x,
+    n :*: LLVM.SizeOf (Marshal.Struct x) ~ arraySize,
+    TypeNum.Natural arraySize,
+    Tuple.Undefined b, Tuple.Phi b, A.Additive b) =>
+   (Exp x -> Causal.T a b) ->
+   Exp (MultiValue.Array n x) -> Causal.T a b
+multiMix f ps =
+   Causal.replicateControlledParam (\x -> Causal.mix <<< first (f x)) ps
+   <<^
+   (\a -> (a, A.zero))
+
+stereoOsciSawVector :: Float -> SVL.Vector (Stereo.T Float)
+stereoOsciSawVector freq =
+   Unsafe.performIO $
+   (\f -> uncurry (f tonesChunkSize) (stereoOsciParams TypeNum.d5 freq))
+   <$>
+   Render.run stereoOsciSawP
+
+stereoOsciSawChord :: NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float)
+stereoOsciSawChord =
+   NonEmpty.foldBalanced mixVectorStereo . fmap stereoOsciSawVector
+
+stereoOsciSawPad :: Word -> NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float)
+stereoOsciSawPad dur pitches =
+   let attack = 20000
+   in Unsafe.performIO $
+      fmap
+         (\f ->
+            Unsafe.performIO $
+            pioApply (f attack (dur-attack)) (stereoOsciSawChord pitches)) $
+      CausalRender.run
+         (\intro len ->
+            Stereo.multiValue <$>
+               (Causal.envelopeStereo $< fadeEnvelope intro len)
+                  <<^ Stereo.unMultiValue)
+
+a0, as0, b0, c1, cs1, d1, ds1, e1, f1, fs1, g1, gs1,
+ a1, as1, b1, c2, cs2, d2, ds2, e2, f2, fs2, g2, gs2,
+ a2, as2, b2, c3, cs3, d3, ds3, e3, f3, fs3, g3, gs3,
+ a3, as3, b3, c4, cs4, d4, ds4, e4, f4, fs4, g4, gs4 :: Float
+a0 : as0 : b0 : c1 : cs1 : d1 : ds1 : e1 : f1 : fs1 : g1 : gs1 :
+ a1 : as1 : b1 : c2 : cs2 : d2 : ds2 : e2 : f2 : fs2 : g2 : gs2 :
+ a2 : as2 : b2 : c3 : cs3 : d3 : ds3 : e3 : f3 : fs3 : g3 : gs3 :
+ a3 : as3 : b3 : c4 : cs4 : d4 : ds4 : e4 : f4 : fs4 : g4 : gs4 : _ =
+  iterate ((2 ** recip 12) *) (55/44100)
+
+
+chordSequence :: [(Word, NonEmpty.T [] Float)]
+chordSequence =
+   (2, f1  !: f2  : a2 : c3 : []) :
+   (1, g1  !: g2  : b2 : d3 : []) :
+   (2, c2  !: g2  : c3 : e3 : []) :
+   (1, f1  !: a2  : c3 : f3 : []) :
+   (2, g1  !: g2  : b2 : d3 : []) :
+   (1, gs1 !: gs2 : b2 : e3 : []) :
+   (2, a1  !: e2  : a2 : c3 : []) :
+   (1, g1  !: g2  : b2 : d3 : []) :
+   (3, c2  !: g2  : c3 : e3 : []) :
+
+   (2, f1  !: f2  : a2 : c3 : []) :
+   (1, g1  !: g2  : b2 : d3 : []) :
+   (2, c2  !: g2  : c3 : e3 : []) :
+   (1, f1  !: a2  : c3 : f3 : []) :
+   (2, g1  !: g2  : b2 : d3 : []) :
+   (1, gs1 !: gs2 : b2 : e3 : []) :
+   (2, a1  !: e2  : a2 : c3 : []) :
+   (1, g1  !: g2  : b2 : e3 : []) :
+   (3, c2  !: e2  : g2 : c3 : []) :
+   []
+
+
+withDur :: (Word -> a -> v) -> Word -> a -> (v, NonNeg.Int)
+withDur f d ps =
+   let dur = d*30000
+   in  (f dur ps, NonNeg.fromNumber $ fromIntegral dur)
+
+
+padMusic :: IO ()
+padMusic = do
+   arrange <- SigStL.makeArranger
+   amplify <-
+      CausalRender.run $ \volume ->
+         Stereo.multiValue ^<<
+         Causal.amplifyStereo volume <<^
+         Stereo.unMultiValue
+   (playStereoVector =<<) $
+      pioApply (amplify (0.1::Float)) $
+      arrange tonesChunkSize $
+      EventListTM.switchTimeR const $
+      EventListMT.consTime 0 $
+      EventListBT.fromPairList $
+      map (\(d,ps) -> withDur stereoOsciSawPad d ps)
+      chordSequence
+
+
+lowpassSweepControlRateCausal ::
+   Causal.T
+      (Stereo.T (MultiValue.T Float))
+      (Stereo.T (MultiValue.T Float))
+lowpassSweepControlRateCausal =
+--   Causal.stereoFromVector $
+   Causal.stereoFromMono $
+      UniFilter.lowpass ^<<
+      Ctrl.processCtrlRate 128
+         (lfoSine (UniFilter.parameter (10::Exp Float)))
+
+
+moogSweepControlRateCausal ::
+   Causal.T
+      (Stereo.T (MultiValue.T Float))
+      (Stereo.T (MultiValue.T Float))
+moogSweepControlRateCausal =
+--   Causal.stereoFromVector $
+   Causal.stereoFromMono $
+      Ctrl.processCtrlRate 128
+         (lfoSine (Moog.parameter TypeNum.d8 (10::Exp Float)))
+
+
+filterMusic :: IO ()
+filterMusic = do
+   arrange <- SigStL.makeArranger
+   pad <- stereoOsciSawPadIO
+   proc <-
+      CausalRender.run $ \volume ->
+         Stereo.multiValue ^<<
+         Causal.amplifyStereo volume <<<
+         moogSweepControlRateCausal <<^
+         Stereo.unMultiValue
+   (playStereoVector =<<) $
+      pioApply (proc (0.05::Float)) $
+      arrange tonesChunkSize $
+      EventListTM.switchTimeR const $
+      EventListMT.consTime 0 $
+      EventListBT.fromPairList $
+      map (\(d,ps) -> withDur pad d ps)
+      chordSequence
+
+
+
+stereoOsciSawVectorIO :: IO (Float -> SVL.Vector (Stereo.T Float))
+stereoOsciSawVectorIO =
+   (\f freq -> uncurry (f tonesChunkSize) (stereoOsciParams TypeNum.d5 freq))
+   <$>
+   Render.run stereoOsciSawP
+
+applyFadeEnvelopeIO ::
+   IO (Word -> SVL.Vector (Stereo.T Float) -> SVL.Vector (Stereo.T Float))
+applyFadeEnvelopeIO =
+   let attack = 20000 in
+   fmap
+      (\f dur sig ->
+         Unsafe.performIO $ pioApply (f attack (dur-attack)) sig) $
+   CausalRender.run
+      (\intro len ->
+         Stereo.multiValue <$>
+            (Causal.envelopeStereo $< fadeEnvelope intro len)
+               <<^ Stereo.unMultiValue)
+
+stereoOsciSawChordIO :: IO (NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float))
+stereoOsciSawChordIO = do
+   sawv <- stereoOsciSawVectorIO
+   mix <- mixVectorStereoIO
+   return (NonEmpty.foldBalanced mix . fmap sawv)
+
+stereoOsciSawPadIO ::
+   IO (Word -> NonEmpty.T [] Float -> SVL.Vector (Stereo.T Float))
+stereoOsciSawPadIO = do
+   chrd <- stereoOsciSawChordIO
+   envelope <- applyFadeEnvelopeIO
+   return $
+      \ dur pitches -> envelope dur (chrd pitches)
+
+padMusicIO :: IO ()
+padMusicIO = do
+   arrange <- SigStL.makeArranger
+   pad <- stereoOsciSawPadIO
+   amplify <-
+      CausalRender.run $ \volume ->
+         Stereo.multiValue ^<<
+         Causal.amplifyStereo volume <<^
+         Stereo.unMultiValue
+   (playStereoVector =<<) $
+      pioApply (amplify (0.08::Float)) $
+      arrange tonesChunkSize $
+      EventListTM.switchTimeR const $
+      EventListMT.consTime 0 $
+      EventListBT.fromPairList $
+      map (uncurry (withDur pad)) $
+      chordSequence
+
+{-
+Apply the envelope separately to each tone of the chord
+and mix all tones by 'arrange'.
+-}
+padMusicSeparate :: IO ()
+padMusicSeparate = do
+   arrange <- SigStL.makeArranger
+   osci <- stereoOsciSawVectorIO
+   env <- applyFadeEnvelopeIO
+   amplify <-
+      CausalRender.run $ \volume ->
+         Stereo.multiValue ^<<
+         Causal.amplifyStereo volume <<^
+         Stereo.unMultiValue
+   (playStereoVector =<<) $
+      pioApply (amplify (0.08::Float)) $
+      arrange tonesChunkSize $
+      EventList.flatten $
+      EventListTM.switchTimeR const $
+      EventListMT.consTime 0 $
+      EventListBT.fromPairList $
+      map (uncurry (withDur (\d ps ->
+         map (\p -> env d (osci p)) $ NonEmpty.flatten ps))) $
+      chordSequence
+
+
+delay :: IO ()
+delay =
+   (SVL.writeFile "speedtest.f32" . asMono =<<) $
+   fmap (\f -> f tonesChunkSize (0::Word) (10000::Word)) $
+   Render.run $ \del dur ->
+      Causal.delayZero del . Causal.take dur
+      $*
+      Sig.osci Wave.saw 0 (frequency 0.01)
+
+delayStereo :: IO ()
+delayStereo =
+   (SVL.writeFile "speedtest.f32" . asStereo =<<) $
+   fmap (\f -> f tonesChunkSize (7::Word) (10000::Word)) $
+   Render.run $ \del dur ->
+      Causal.take dur . liftA2 Stereo.consMultiValue id (Causal.delayZero del)
+      $*
+      Sig.osci Wave.saw 0 (frequency 0.01)
+
+delayPhaser :: IO ()
+delayPhaser =
+   (SVL.writeFile "speedtest.f32" . asStereo =<<) $
+   fmap (\f -> f tonesChunkSize (40000::Word)) $
+   Render.run $ \dur ->
+   Func.compileSignal $
+      let osci = Func.fromSignal $ Sig.osci Wave.saw 0 (frequency 0.01)
+          ctrl =
+             Func.fromSignal $
+             Sig.osci Wave.triangle 0 $ frequency (1/20000)
+      in  Causal.take dur $&
+          liftA2 Stereo.consMultiValue
+             osci
+             (Causal.delayControlledInterpolated Interpolation.cubic 0 100
+              $&
+              (50+50*ctrl) &|& osci)
+
+
+
+allpassControl ::
+   (TypeNum.Natural n) =>
+   Proxy n -> Exp Float ->
+   Sig.T (Allpass.CascadeParameter n (MultiValue.T Float))
+allpassControl order reduct =
+   Sig.interpolateConstant reduct $
+   lfoSine (Allpass.flangerParameter order) reduct
+
+allpassPhaserCausal, allpassPhaserPipeline ::
+   Exp Float ->
+   Sig.MV Float ->
+   Sig.MV Float
+allpassPhaserCausal reduct xs =
+   let order = TypeNum.d16
+   in 0.5 * Allpass.phaser $< allpassControl order reduct $* xs
+
+allpassPhaserPipeline reduct xs =
+   let order = TypeNum.d16
+   in (nest (TypeNum.integralFromProxy order) Sig.tail) $
+      -- Sig.drop
+      --    (TypeNum.integralFromProxy order)
+         (0.5 * Allpass.phaserPipeline $< allpassControl order reduct $* xs)
+
+allpassPhaser :: IO ()
+allpassPhaser =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap (\f -> f (SVL.chunkSize 100000) (128::Float)) $
+   Render.run $
+   \reduct ->
+--      allpassPhaserCausal reduct $
+      allpassPhaserPipeline reduct $
+      Sig.osci Wave.saw 0 (frequency 0.01)
+
+noise :: IO ()
+noise =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run $
+   Sig.noise 0 0.3
+
+noisePacked :: IO ()
+noisePacked =
+   (SVL.writeFile "speedtest.f32" . asMonoPacked
+      . SVL.take (div 10000000 4) =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run $
+   SigPS.noise 0 0.3
+--   SigPS.pack (SigP.noise 0 0.3)
+--   SigPS.packSmall (SigP.noise 0 0.3)
+
+frequencyModulationStorable :: IO ()
+frequencyModulationStorable = do
+   sample <- Render.run $ Sig.osci Wave.saw 0 (frequency 0.01)
+   f <-
+      Render.run $ \smp ->
+         Causal.frequencyModulationLinear smp $* 0.3
+   SVL.writeFile "speedtest.f32" . asMono $
+      f (SVL.chunkSize 100000) $ SVL.take 1000000 $ sample (SVL.chunkSize 1000)
+
+
+frequencyModulation :: IO ()
+frequencyModulation =
+   (SVL.writeFile "speedtest.f32" . asMono . SVL.take 10000000 =<<) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (Causal.frequencyModulationLinear (Sig.osci Wave.saw 0 (frequency 0.01))
+       $* Sig.exponential2 500000 1)
+
+frequencyModulationStereo :: IO ()
+frequencyModulationStereo = do
+   sample <- Render.run $ Sig.osci Wave.saw 0 (frequency 0.01)
+   f <-
+      Render.run $ \smp ->
+         Stereo.multiValue ^<<
+         Causal.stereoFromMono (Causal.frequencyModulationLinear smp)
+            $* Sig.constant (Stereo.cons 0.2999 0.3001)
+   SVL.writeFile "speedtest.f32" . asStereo $
+      f (SVL.chunkSize 100000) $ SVL.take 1000000 $ sample (SVL.chunkSize 1000)
+
+frequencyModulationProcess :: IO ()
+frequencyModulationProcess = do
+   proc <-
+      CausalRender.run
+         (Causal.frequencyModulationLinear
+            (Causal.take 50000 $* Sig.osci Wave.saw 0 (frequency 0.01)))
+   sample <- Render.run (1 + 0.1 * Sig.osci Wave.approxSine2 0 0.0001)
+   SVL.writeFile "speedtest.f32" . asMono =<<
+      pioApply proc (sample (SVL.chunkSize 512))
+
+
+
+quantize :: IO ()
+quantize =
+{-
+   SV.writeFile "speedtest.f32" $
+   asMono $
+   (\xs -> SigP.render xs 10000000 ()) $
+-}
+   (SVL.writeFile "speedtest.f32" . asMono =<<) $
+   fmap (SVL.take 10000000) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run $
+      (Causal.quantizeLift id
+         $<# (5.5::Float)
+         $* Sig.osci Wave.saw 0 (frequency 0.01))
+
+quantizedFilterControl :: IO ()
+quantizedFilterControl =
+   (SVL.writeFile "speedtest.f32" . asMono =<<) $
+   fmap (SVL.take 10000000) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (0.3 * (UniFilter.lowpass ^<< Ctrl.process)
+       $< (Causal.quantizeLift
+            (Causal.map (UniFilter.parameter 100) <<<
+   --         (Causal.map (Moog.parameter TypeNum.d8 100) <<<
+             Causal.map (\x -> 0.01 * exp (2 * x)))
+            $<# (128::Float)
+            $* Sig.osci Wave.approxSine2 0 (frequency (0.1/44100)))
+       $* Sig.osci Wave.saw 0 (frequency 0.01))
+
+
+arrowNonShared :: IO ()
+arrowNonShared =
+   (SVL.writeFile "speedtest.f32" . asStereo =<<) $
+   fmap (SVL.take 10000000) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (let osci = Causal.osci Wave.approxSine2
+       in liftA2 Stereo.consMultiValue osci osci $* Sig.constant (0, 0.01))
+
+arrowShared :: IO ()
+arrowShared =
+   (SVL.writeFile "speedtest.f32" . asStereo =<<) $
+   fmap (SVL.take 10000000) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (let osci = Func.lift $ Causal.osci Wave.approxSine2
+       in Func.compile (liftA2 Stereo.consMultiValue osci osci) $*
+          Sig.constant (0, 0.01))
+
+arrowIndependent :: IO ()
+arrowIndependent =
+   (SVL.writeFile "speedtest.f32" . asStereo =<<) $
+   fmap (SVL.take 10000000) $
+   fmap ($ SVL.chunkSize 100000) $
+   Render.run
+      (let osci = Causal.osci Wave.approxSine2
+       in Func.compile
+               (uncurry Stereo.consMultiValue  <$>
+                  (osci *** osci  $&  Func.lift id)) $*
+            Sig.constant ((0, 0.01), (0.25, 0.01001)))
+
+
+rampDown :: Int -> SV.Vector Float
+rampDown n =
+   SigS.toStrictStorableSignal n $
+   CtrlS.line n (1, 0)
+
+impulses :: Int -> Float -> SVL.Vector Float
+impulses n x =
+   SVL.fromChunks $
+   concatMap (\k -> [SV.singleton x, SV.replicate k 0]) $
+   take n $ iterate (2*) 1
+
+convolution :: IO ()
+convolution =
+   (SVL.writeFile "speedtest.f32" . asMono =<<) $
+   ((\f ->
+      pioApply (f $ Render.buffer $ rampDown 1000) (impulses 18 0.1)) =<<) $
+   CausalRender.run FiltNR.convolve
+
+convolutionPacked :: IO ()
+convolutionPacked = do
+   pack <- Render.run SigPS.pack
+   impulsesPacked <- pack SVL.defaultChunkSize $ impulses 18 0.1
+   (SVL.writeFile "speedtest.f32" . asMonoPacked =<<) $
+      ((\f ->
+         pioApply (f $ Render.buffer $ rampDown 1000) impulsesPacked) =<<) $
+      CausalRender.run FiltNR.convolvePacked
+
+
+helixSaw :: IO ()
+helixSaw = do
+   let srcFreq = 0.01
+       srcLength :: Word
+       srcLength = 40000
+   osci <- Render.run $ \dur -> Sig.osci Wave.saw 0 srcFreq * (1-Sig.ramp dur)
+   let perc =
+         asMono $ osci (fromIntegral srcLength) srcLength
+   SV.writeFile "osci-saw.f32" perc
+   stretched <-
+      Render.run $ \dur sig ->
+      Func.compileSignal $
+      (Helix.static Interpolation.cubic Interpolation.cubic
+            100 (recip srcFreq) sig
+         $&
+         (Func.fromSignal $ Sig.amplify (fromIntegral srcLength) $ Sig.ramp dur)
+         &|&
+         (Causal.osciCore $& 0 &|& 0.01))
+   SVL.writeFile "osci-stretched.f32" . asMono =<<
+      stretched SVL.defaultChunkSize (80000::Word) (Render.buffer perc)
+
+
+loadTomato :: IO (Float, SVL.Vector Float)
+loadTomato = do
+   let Sample.Info name _sampleRate positions = Sample.tomatensalat
+   word <- Sample.load (Default.sampleDirectory </> name)
+   return (Sample.period $ head positions, word)
+
+helixOsci :: Exp Float -> Func.T a (MultiValue.T Float)
+helixOsci period =
+   Causal.osciCore  $&  0 &|& Func.fromSignal (Sig.constant (recip period))
+
+helixSpeechStaticSig ::
+   Func.T () (MultiValue.T Float) ->
+   Exp (Source.StorableVector Float) ->
+   Exp Float ->
+   Sig.MV Float
+helixSpeechStaticSig shape word period =
+   Func.compileSignal
+      (Helix.static Interpolation.linear Interpolation.linear
+          (Expr.roundToIntFast period) period word
+       $&
+       shape
+       &|&
+       helixOsci period)
+
+helixSpeechStaticSpeed ::
+   Exp Float ->
+   Exp (Source.StorableVector Float) ->
+   Exp Float ->
+   Sig.MV Float
+helixSpeechStaticSpeed speed word =
+   helixSpeechStaticSig
+      (Func.fromSignal
+         (Causal.takeWhile
+            (Expr.fromIntegral (Source.storableVectorLength word) >*)
+          $*
+          Sig.rampSlope speed))
+      word
+
+helixSpeechStatic :: IO ()
+helixSpeechStatic = do
+   smp <- loadTomato
+   stretched <-
+      Render.run $ \speed (period, word) ->
+         helixSpeechStaticSpeed speed word period
+   (SVL.writeFile "speech-stretched.f32" . asMono =<<) $
+      stretched SVL.defaultChunkSize (0.5::Float) $
+      mapSnd (Render.buffer . SV.concat . SVL.chunks) smp
+
+helixSpeechDynamicSig ::
+   Func.T () (MultiValue.T Float) ->
+   Sig.MV Float ->
+   Exp Float ->
+   Sig.MV Float
+helixSpeechDynamicSig shape word period =
+   Func.compileSignal
+      (Helix.dynamicLimited Interpolation.linear Interpolation.linear
+          (Expr.roundToIntFast period) period word
+       $&
+       shape
+       &|&
+       helixOsci period)
+
+helixSpeechDynamicSpeed ::
+   Exp Float ->
+   Sig.MV Float ->
+   Exp Float ->
+   Sig.MV Float
+helixSpeechDynamicSpeed speed =
+   helixSpeechDynamicSig (Func.fromSignal $ Sig.constant speed)
+
+helixSpeechDynamic :: IO ()
+helixSpeechDynamic = do
+   smp <- loadTomato
+   stretched <-
+      Render.run $ \speed (period, word) ->
+      helixSpeechDynamicSpeed speed word period
+   SVL.writeFile "speech-stretched.f32" $ asMono $
+      stretched SVL.defaultChunkSize (0.5::Float) smp
+
+helixSpeechCompare :: IO ()
+helixSpeechCompare = do
+   (per,smp) <- loadTomato
+   stretched <-
+      Render.run $ \speed period word wordBuffer ->
+      fmap Stereo.multiValue $
+      sequenceA $
+      Stereo.cons
+         (helixSpeechStaticSpeed speed wordBuffer period)
+         (helixSpeechDynamicSpeed speed word period)
+   SVL.writeFile "speech-stretched.f32" $ asStereo $
+      stretched SVL.defaultChunkSize (0.5::Float)
+         per smp (Render.buffer . SV.concat . SVL.chunks $ smp)
+
+helixSpeechVariCompare :: IO ()
+helixSpeechVariCompare = do
+   (per,smp) <- loadTomato
+   stretched <-
+      Render.run $ \period word wordBuffer ->
+      fmap Stereo.multiValue $
+      sequenceA $
+      let speed =
+             Func.fromSignal $ Sig.cycle $
+             Sig.fromArray $ Expr.cons $
+             (MultiValue.Array [0.2, 0.5, 1, 1.5, 1.8]
+                :: MultiValue.Array TypeNum.D5 Float)
+      in  Stereo.cons
+             (helixSpeechStaticSig
+                 (Causal.integrateZero $& speed)
+                 wordBuffer period)
+             (helixSpeechDynamicSig speed word period)
+   SVL.writeFile "speech-stretched.f32" $ asStereo $
+      stretched SVL.defaultChunkSize
+         per smp (Render.buffer . SV.concat . SVL.chunks $ smp)
+
+helixLimited :: IO ()
+helixLimited = do
+   let period = 100
+       srcLength :: Int
+       srcLength = 500
+       dstLength = 5000
+       speed :: Exp Float
+       speed = 0.5
+       osci =
+          0.5
+          *
+          Sig.ramp (fromIntegral srcLength)
+          *
+          Sig.osci Wave.approxSine2 0 (recip period)
+   renderOsci <- Render.run osci
+   let osciVec = renderOsci srcLength
+   SV.writeFile "helix-orig.f32" $ asMono osciVec
+
+   let stretchedStatic osciBuffer =
+          Helix.static Interpolation.linear Interpolation.linear
+             (Expr.roundToIntFast period) period osciBuffer
+          $&
+          Func.fromSignal (Sig.rampSlope speed)
+          &|&
+          helixOsci period
+       stretchedDynamic =
+          Helix.dynamic Interpolation.linear Interpolation.linear
+             (Expr.roundToIntFast period) period osci
+          $&
+          Func.fromSignal (Sig.constant speed)
+          &|&
+          helixOsci period
+       stretched osciBuffer =
+          liftA2 Stereo.consMultiValue
+             (stretchedStatic osciBuffer) stretchedDynamic
+   renderHelix <- Render.run $ Func.compileSignal . stretched
+   SV.writeFile "helix-stretched.f32" $ asStereo $
+      renderHelix dstLength (Render.buffer osciVec)
+
+cycleRamp :: IO ()
+cycleRamp =
+   SVL.writeFile "speedtest.f32" . asMono .
+         (\f -> f SVL.defaultChunkSize (10000::Word)) =<<
+      Render.run
+         (\dur ->
+            Causal.take 100000 $*
+            Sig.cycle (Sig.append (Sig.ramp dur) (1 - Sig.ramp dur)))
+
+zigZag :: IO ()
+zigZag =
+   SVL.writeFile "speedtest.f32" . asMono .
+         (\f -> f SVL.defaultChunkSize (-3::Float)) =<<
+      Render.run
+         (\start -> Causal.take 100000 $* (Helix.zigZag start $* 0.0001))
+
+zigZagPacked :: IO ()
+zigZagPacked =
+   SVL.writeFile "speedtest.f32" . asMonoPacked .
+         (\f -> f SVL.defaultChunkSize (-3::Float)) =<<
+      Render.run
+         (\start ->
+            let vectorSize = 4
+            in Causal.take (fromInteger $ div 100000 vectorSize) $*
+                  (Helix.zigZagPacked start $* 0.0001))
+
+
+trigger :: IO ()
+trigger =
+   (SVL.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ SVL.defaultChunkSize) $
+      Render.run
+         (let pause len =
+                 CausalClass.applyConst (Causal.take len) Maybe.nothing
+              pulse :: Float -> Exp Word -> Sig.T (Maybe.T (MultiValue.T Float))
+              pulse freq len =
+                 Causal.take len .
+                 arr (flip Maybe.fromBool (MultiValue.cons freq) . unbool) .
+                 Causal.delay1 Expr.true $*# False
+          in  (Causal.zipWith ExprMaybe.select
+                  $> Sig.noise 0 (0.01 :: Exp Float)) $*
+              (Causal.trigger (\freq -> Causal.take 150000 $* pingSigP freq) $*
+               pause 50000 <>
+               pulse 0.004 100000 <>
+               pulse 0.005 200000 <>
+               pulse 0.006 400000))
+
+-- FixMe: duplicate of CausalExp.ProcessPrivate
+unbool :: MultiValue.T Bool -> LLVM.Value Bool
+unbool (MultiValue.Cons b) = b
+
+
+triggerLFO :: Sig.MV Float
+triggerLFO =
+   Sig.osci Wave.approxSine2 0 0.00015
+   +
+   Sig.osci Wave.approxSine2 0 0.000037
+
+trackZeros :: Causal.MV Float Bool
+trackZeros =
+   Causal.zipWith (\x y -> x &&* Expr.not y) .
+   (id &&& Causal.delay1 Expr.false) .
+   Causal.map (>* 0)
+
+fmPingSig :: Exp Float -> Exp Float -> Sig.MV Float
+fmPingSig freq depth =
+   Sig.exponential2 5000 1
+   *
+   ((Causal.osci Wave.approxSine2 $> Sig.constant freq)
+    $*
+    (Sig.constant depth * Sig.osci Wave.approxSine2 0 (2*freq)))
+
+sweepTrigger :: IO ()
+sweepTrigger =
+   (SVL.writeFile "speedtest.f32" . asMono =<<) $
+   fmap ($ SVL.defaultChunkSize) $
+      Render.run
+         ((Causal.zipWith ExprMaybe.select $> Sig.noise 0 0.01) $*
+            (Causal.trigger (fmPingSig 0.005) $*
+               liftA2 (Maybe.fromBool . unbool)
+                  (Causal.take 10000000 . trackZeros $* triggerLFO)
+                  (5 * Sig.osci Wave.approxSine2 0 0.00001)))
 
 
 main :: IO ()
diff --git a/example/Synthesizer/LLVM/TestALSA.hs b/example/Synthesizer/LLVM/TestALSA.hs
--- a/example/Synthesizer/LLVM/TestALSA.hs
+++ b/example/Synthesizer/LLVM/TestALSA.hs
@@ -2,6 +2,11 @@
 
 import qualified Synthesizer.LLVM.LNdW2011 as LNdW
 
+import Control.Monad (when)
 
+
 main :: IO ()
-main = LNdW.flyPacked
+main = do
+   when True LNdW.flyPacked
+   when False LNdW.modulation
+   when False LNdW.bubblesPacked
diff --git a/jack/Synthesizer/LLVM/Server/JACK.hs b/jack/Synthesizer/LLVM/Server/JACK.hs
--- a/jack/Synthesizer/LLVM/Server/JACK.hs
+++ b/jack/Synthesizer/LLVM/Server/JACK.hs
@@ -13,13 +13,16 @@
 import qualified Synthesizer.MIDI.CausalIO.Process as MIO
 import qualified Synthesizer.CausalIO.Process as PIO
 
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Process as Causal
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 
 import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoInt
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 
+import qualified Type.Data.Num.Decimal as TypeNum
+
 import qualified Data.StorableVector as SV
 import qualified Data.StorableVector.Base as SVB
 import Foreign.Marshal.Array (copyArray)
@@ -47,9 +50,8 @@
 import qualified System.Path.PartClass as PathClass
 import qualified System.Path as Path
 
-import Control.Arrow ((<<<), (^<<), arr)
+import Control.Arrow (arr, (<<<), (^<<))
 import Control.Category (id)
-import Control.Applicative (pure)
 
 import qualified System.Random as Random
 import qualified Numeric.NonNegative.Wrapper as NonNegW
@@ -205,11 +207,11 @@
 keyboardMultiChannel = do
    opt <- Option.get
    proc <- keyboardDetuneFMCore (Option.sampleDirectory opt)
-   mix <- CausalP.processIO CausalP.mix
+   mix <- CausalRender.run Causal.mix
 
    playStereoFromEvents opt $ \ sampleRate ->
       foldl1
-         (\x y -> mix () <<< Zip.arrowFanout x y)
+         (\x y -> mix <<< Zip.arrowFanout x y)
          (map
              (\chan ->
                 proc (ChannelMsg.toChannel chan) (VoiceMsg.toProgram 0)
@@ -232,24 +234,29 @@
 voderMaskSeparated :: IO ()
 voderMaskSeparated = do
    opt <- Option.get
-   let postProcessing =
+   let postProcessing params =
           if True
             then
-               let reverb seed =
-                      CausalP.reverb
-                         (pure $ Random.mkStdGen seed) 16 (pure (0.92,0.98))
-                         (fmap (\(SampleRate rate) -> (round (rate/200), round (rate/40))) id)
-               in  CausalPS.pack (Stereo.arrowFromChannels (reverb 42) (reverb 23))
+               CausalPS.pack
+                  (Stereo.arrowFromChannels
+                     (Causal.reverbExplicit $ Stereo.left params)
+                     (Causal.reverbExplicit $ Stereo.right params))
             else id
    proc <-
       Arrange.voderMaskSeparated
-         (arr unconsStereo <<< postProcessing)
+         (\reverbParams -> unconsStereo ^<< postProcessing reverbParams)
          (Option.sampleDirectory opt)
 
-   playStereoFromEvents opt $ \ sampleRate ->
+   playStereoFromEvents opt $ \ sampleRate@(SampleRate rate) ->
       proc
          (Option.channel opt) (Option.extraChannel opt)
          (VoiceMsg.toProgram 4) sampleRate
+         (fmap
+            (\seed ->
+               Causal.reverbParams
+                  (Random.mkStdGen seed) TypeNum.d16 (0.92,0.98)
+                  (round (rate/200), round (rate/40)))
+            (Stereo.cons 42 23))
 
 
 main :: IO ()
diff --git a/render/Synthesizer/LLVM/Server/Render.hs b/render/Synthesizer/LLVM/Server/Render.hs
--- a/render/Synthesizer/LLVM/Server/Render.hs
+++ b/render/Synthesizer/LLVM/Server/Render.hs
@@ -7,6 +7,7 @@
 
 import qualified Synthesizer.LLVM.Server.Option as Option
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import Synthesizer.LLVM.Server.CausalPacked.Common (chopEvents)
 import Synthesizer.LLVM.Server.Common
 
 import qualified Synthesizer.CausalIO.Process as PIO
@@ -59,7 +60,7 @@
 render :: Option.T -> IO (MidiFile.T -> SVL.Vector (Stereo.T Real))
 render opt = do
    proc <-
-      case 0::Int of
+      case fromInteger 0 :: Int of
          0 -> Arrange.keyboardMultiChannel $ Option.sampleDirectory opt
          _ -> Arrange.voderMaskMulti $ Option.sampleDirectory opt
    run <- PIO.runCont $ proc $ fmap fromIntegral $ Option.sampleRate opt
diff --git a/server/Synthesizer/LLVM/Server/CausalPacked/Arrange.hs b/server/Synthesizer/LLVM/Server/CausalPacked/Arrange.hs
--- a/server/Synthesizer/LLVM/Server/CausalPacked/Arrange.hs
+++ b/server/Synthesizer/LLVM/Server/CausalPacked/Arrange.hs
@@ -1,6 +1,7 @@
 module Synthesizer.LLVM.Server.CausalPacked.Arrange where
 
-import Synthesizer.LLVM.Server.CommonPacked (VectorSize, Vector, VectorValue, stair)
+import Synthesizer.LLVM.Server.CommonPacked
+         (VectorSize, Vector, VectorValue, stair)
 
 import qualified Sound.MIDI.Controller as Ctrl
 
@@ -18,8 +19,10 @@
 import qualified Synthesizer.PiecewiseConstant.Signal as PC
 
 import qualified Synthesizer.LLVM.Plug.Output as POut
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
 import qualified Synthesizer.LLVM.Storable.Process as CausalSt
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 
@@ -42,14 +45,13 @@
 import qualified System.Path.PartClass as PathClass
 import qualified System.Path as Path
 
-import Control.Arrow (Arrow, arr, first, (<<<), (^<<))
+import Control.Arrow (Arrow, arr, (***), (<<<), (^<<), (<<^))
 import Control.Category (id)
 import Control.Applicative ((<*>))
 
 import qualified Data.List.HT as ListHT
-import Data.Maybe.HT (toMaybe)
-
 import qualified Data.Map as Map
+import Data.Maybe.HT (toMaybe)
 
 import qualified Number.DimensionTerm as DN
 import qualified Algebra.DimensionTerm as Dim
@@ -72,12 +74,12 @@
        PIO.T (MIO.Events msg) (SV.Vector Vector))
 keyboard = do
    arrange <- CausalSt.makeArranger
-   amp <- CausalP.processIO (CausalPS.amplify 0.2)
+   amp <- CausalRender.run (CausalPS.amplify 0.2)
 
    ping <- Instr.pingRelease
 
    return $ \ chan sampleRate ->
-      amp ()
+      amp
       <<<
       arrange
       <<<
@@ -117,19 +119,19 @@
 
 keyboardFM ::
    (Check.C msg, POut.Default b) =>
-   CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->
+   Causal.T (Stereo.T VectorValue) (POut.Element b) ->
    ChannelMsg.Channel ->
    IO (SampleRate Real -> PIO.T (MIO.Events msg) b)
 keyboardFM emitStereo chan = do
    arrange <- CausalSt.makeArranger
    amp <-
-      CausalP.processIO
-         (emitStereo <<< CausalPS.amplifyStereo 0.2)
+      CausalRender.run
+         (emitStereo <<< CausalPS.amplifyStereo 0.2 <<^ Stereo.unMultiValue)
 
    ping <- Instr.pingStereoReleaseFM
 
    return $ \ sampleRate ->
-      amp ()
+      amp
       <<<
       arrange
       <<<
@@ -201,19 +203,19 @@
 
 keyboardDetuneFMCore ::
    (PathClass.AbsRel ar, Check.C msg, POut.Default b) =>
-   CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->
+   Causal.T (Stereo.T VectorValue) (POut.Element b) ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> VoiceMsg.Program ->
        SampleRate Real -> PIO.T (MIO.Events msg) b)
 keyboardDetuneFMCore emitStereo smpDir = do
    arrange <- keyboardDetuneFMConstVolume smpDir
    amp <-
-      CausalP.processIO
+      CausalRender.run
          (emitStereo <<<
-          CausalP.envelopeStereo <<<
-          first (CausalP.mapSimple Serial.upsample))
+          Causal.envelopeStereo <<<
+          Causal.map Serial.upsample *** arr Stereo.unMultiValue)
    return $ \chan initPgm rate ->
-      amp ()
+      amp
       <<<
       MIO.controllerExponential chan controllerVolume (0.001, 1) (0.2::Float)
       &+&
@@ -433,15 +435,15 @@
 keyboardMultiChannel smpDir = do
    proc <-
       keyboardDetuneFMCore
-         (CausalP.mapSimple StereoInt.interleave)
+         (Causal.map StereoInt.interleave)
          smpDir
-   mix <- CausalP.processIO CausalP.mix
+   mix <- CausalRender.run Causal.mix
 
    return $ \ sampleRate ->
       arr SigStL.unpackStereoStrict
       <<<
       foldl1
-         (\x y -> mix () <<< Zip.arrowFanout x y)
+         (\x y -> mix <<< Zip.arrowFanout x y)
          (map
              (\chan ->
                 proc (ChannelMsg.toChannel chan) (VoiceMsg.toProgram 0)
@@ -485,18 +487,18 @@
 
 voder ::
    (PathClass.AbsRel ar, Check.C msg, Construct.C msg, POut.Default b) =>
-   CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->
+   Causal.T (Stereo.T VectorValue) (POut.Element b) ->
    Speech.VowelSynth ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> VoiceMsg.Program ->
        SampleRate Real -> PIO.T (MIO.Events msg) b)
 voder emitStereo voice smpDir = do
-   carrier <- keyboardDetuneFMCore id smpDir
+   carrier <- keyboardDetuneFMCore (arr Stereo.multiValue) smpDir
    arrange <- CausalSt.makeArranger
-   interleave <- CausalP.processIO emitStereo
+   interleave <- CausalRender.run (emitStereo <<^ Stereo.unMultiValue)
 
    return $ \chan initPgm sampleRate ->
-      interleave ()
+      interleave
       <<<
       arrange
       <<<
@@ -512,7 +514,7 @@
 
 voderBand ::
    (PathClass.AbsRel ar, Check.C msg, Construct.C msg, POut.Default b) =>
-   CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->
+   Causal.T (Stereo.T VectorValue) (POut.Element b) ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> VoiceMsg.Program ->
        SampleRate Real -> PIO.T (MIO.Events msg) b)
@@ -522,7 +524,7 @@
 
 voderMask ::
    (PathClass.AbsRel ar, Check.C msg, Construct.C msg, POut.Default b) =>
-   CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->
+   Causal.T (Stereo.T VectorValue) (POut.Element b) ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> VoiceMsg.Program ->
        SampleRate Real -> PIO.T (MIO.Events msg) b)
@@ -538,7 +540,7 @@
 
 voderEnv ::
    (PathClass.AbsRel ar, Check.C msg, Construct.C msg, POut.Default b) =>
-   CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->
+   Causal.T (Stereo.T VectorValue) (POut.Element b) ->
    Speech.VowelSynthEnv ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> VoiceMsg.Program ->
@@ -547,13 +549,13 @@
    carrier <- keyboardDetuneFMConstVolume smpDir
    arrange <- CausalSt.makeArranger
    amp <-
-      CausalP.processIO
+      CausalRender.run
          (emitStereo <<<
-          CausalP.envelopeStereo <<<
-          first (CausalP.mapSimple Serial.upsample))
+          Causal.envelopeStereo <<<
+          Causal.map Serial.upsample *** arr Stereo.unMultiValue)
 
    return $ \chan initPgm sampleRate ->
-      amp ()
+      amp
       <<<
       MIO.controllerExponential chan controllerVolume (0.001, 1) (0.2::Float)
       &+&
@@ -574,7 +576,7 @@
 
 voderMaskEnv ::
    (PathClass.AbsRel ar, Check.C msg, Construct.C msg, POut.Default b) =>
-   CausalP.T () (Stereo.T VectorValue) (POut.Element b) ->
+   Causal.T (Stereo.T VectorValue) (POut.Element b) ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> VoiceMsg.Program ->
        SampleRate Real -> PIO.T (MIO.Events msg) b)
@@ -584,23 +586,24 @@
 
 
 voderSeparated ::
-   (PathClass.AbsRel ar, Check.C msg, Construct.C msg, POut.Default b) =>
-   CausalP.T (SampleRate Real) (Stereo.T VectorValue) (POut.Element b) ->
+   (PathClass.AbsRel ar, Render.RunArg p,
+    Check.C msg, Construct.C msg, POut.Default b) =>
+   (Render.DSLArg p -> Causal.T (Stereo.T VectorValue) (POut.Element b)) ->
    Speech.VowelSynthEnv ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> ChannelMsg.Channel -> VoiceMsg.Program ->
-       SampleRate Real -> PIO.T (MIO.Events msg) b)
+       SampleRate Real -> p -> PIO.T (MIO.Events msg) b)
 voderSeparated emitStereo voice smpDir = do
-   carrier <- keyboardDetuneFMCore id smpDir
+   carrier <- keyboardDetuneFMCore (arr Stereo.multiValue) smpDir
    arrange <- CausalSt.makeArranger
    amp <-
-      CausalP.processIO
-         (emitStereo <<<
-          CausalP.envelopeStereo <<<
-          first (CausalP.mapSimple Serial.upsample))
+      CausalRender.run $ \p ->
+         (emitStereo p <<<
+          Causal.envelopeStereo <<<
+          Causal.map Serial.upsample *** arr Stereo.unMultiValue)
 
-   return $ \carrierChan phonemeChan initPgm sampleRate ->
-      amp sampleRate
+   return $ \carrierChan phonemeChan initPgm sampleRate p ->
+      amp p
       <<<
       MIO.controllerExponential phonemeChan controllerVolume (0.001, 1) (0.2::Float)
       &+&
@@ -618,11 +621,12 @@
              (carrier carrierChan initPgm sampleRate)))
 
 voderMaskSeparated ::
-   (PathClass.AbsRel ar, Check.C msg, Construct.C msg, POut.Default b) =>
-   CausalP.T (SampleRate Real) (Stereo.T VectorValue) (POut.Element b) ->
+   (PathClass.AbsRel ar, Render.RunArg p,
+    Check.C msg, Construct.C msg, POut.Default b) =>
+   (Render.DSLArg p -> Causal.T (Stereo.T VectorValue) (POut.Element b)) ->
    Path.Dir ar ->
    IO (ChannelMsg.Channel -> ChannelMsg.Channel -> VoiceMsg.Program ->
-       SampleRate Real -> PIO.T (MIO.Events msg) b)
+       SampleRate Real -> p -> PIO.T (MIO.Events msg) b)
 voderMaskSeparated emitStereo smpDir = do
    voice <- Speech.phonemeMask <*> Speech.loadMasksGrouped
    voderSeparated emitStereo voice smpDir
@@ -633,22 +637,22 @@
    IO (SampleRate Real ->
        PIO.T (MIO.Events msg) (SV.Vector (Stereo.T Real)))
 voderMaskMulti smpDir = do
-   mix <- CausalP.processIO CausalP.mix
+   mix <- CausalRender.run Causal.mix
    proc <-
       voderMaskSeparated
-         (CausalP.mapSimple StereoInt.interleave)
+         (const $ Causal.map StereoInt.interleave)
          smpDir
 
    return $ \ sampleRate ->
       arr SigStL.unpackStereoStrict
       <<<
       foldl1
-         (\x y -> mix () <<< Zip.arrowFanout x y)
+         (\x y -> mix <<< Zip.arrowFanout x y)
          (map
              (\chan ->
                 proc
                    (ChannelMsg.toChannel chan)
                    (ChannelMsg.toChannel $ succ chan)
                    (VoiceMsg.toProgram 4)
-                   sampleRate)
+                   sampleRate ())
              [0, 2, 4, 6])
diff --git a/src/Synthesizer/LLVM/Causal/Controlled.hs b/src/Synthesizer/LLVM/Causal/Controlled.hs
--- a/src/Synthesizer/LLVM/Causal/Controlled.hs
+++ b/src/Synthesizer/LLVM/Causal/Controlled.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE UndecidableInstances #-}
 {- |
 This module provides a type class that automatically selects a filter
@@ -10,9 +11,13 @@
 because there may be different ways to specify the filter parameters
 but there is only one implementation of the filter itself.
 -}
-module Synthesizer.LLVM.Causal.Controlled (C(..)) where
+module Synthesizer.LLVM.Causal.Controlled (
+   C(..),
+   processCtrlRate,
+   ) where
 
-import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as ComplexFiltPack
+import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked
+                                                           as ComplexFiltPack
 import qualified Synthesizer.LLVM.Filter.ComplexFirstOrder as ComplexFilt
 import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
 import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1
@@ -22,30 +27,48 @@
 import qualified Synthesizer.LLVM.Filter.Moog as Moog
 import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
 
-import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 
+import Synthesizer.Causal.Class (($<))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
 import qualified LLVM.Extra.Arithmetic as A
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core (Value, IsConst)
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal.Number ((:*:))
 
+import qualified Algebra.Module as Module
 
+
+
+processCtrlRate ::
+   (C parameter a b, Memory.C parameter) =>
+   (Marshal.C r, MultiValue.IntegerConstant r,
+    MultiValue.Additive r, MultiValue.Comparison r) =>
+   Exp r -> (Exp r -> Sig.T parameter) -> Causal.T a b
+processCtrlRate reduct ctrlGen =
+   process $< Sig.interpolateConstant reduct (ctrlGen reduct)
+
+
 {- |
 A filter parameter type uniquely selects a filter function.
 However it does not uniquely determine the input and output type,
 since the same filter can run on mono and stereo signals.
 -}
 class (a ~ Input parameter b, b ~ Output parameter a) => C parameter a b where
-   type Input  parameter b :: *
-   type Output parameter a :: *
-   process :: (Causal.C process) => process (parameter, a) b
+   type Input  parameter b
+   type Output parameter a
+   process :: Causal.T (parameter, a) b
 
 
 {-
@@ -54,7 +77,7 @@
 -}
 
 instance
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a,
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v,
     Memory.C a, Memory.C v) =>
       C (Filt1.Parameter a) v (Filt1.Result v) where
    type Input  (Filt1.Parameter a) (Filt1.Result v) = v
@@ -70,27 +93,25 @@
    process = Filt2.causal
 
 instance
-   (Vector.Arithmetic a, SoV.RationalConstant a,
-    Memory.C (Value (Filt2P.State a))) =>
-      C (Filt2P.Parameter a)
-        (Value a) (Value a) where
-   type Input  (Filt2P.Parameter a) (Value a) = Value a
-   type Output (Filt2P.Parameter a) (Value a) = Value a
+   (Marshal.C a, Marshal.Vector TypeNum.D4 a, MultiVector.PseudoRing a) =>
+      C (Filt2P.Parameter a) (MultiValue.T a) (MultiValue.T a) where
+   type Input  (Filt2P.Parameter a) (MultiValue.T a) = MultiValue.T a
+   type Output (Filt2P.Parameter a) (MultiValue.T a) = MultiValue.T a
    process = Filt2P.causal
 
 instance
-   (LLVM.IsSized v, SoV.PseudoModule v, SoV.Scalar v ~ a,
-    LLVM.IsSized a, SoV.IntegerConstant a,
-    TypeNum.Natural n,
-    TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-      C (Cascade.ParameterValue n a) (Value v) (Value v) where
-   type Input  (Cascade.ParameterValue n a) (Value v) = Value v
-   type Output (Cascade.ParameterValue n a) (Value v) = Value v
+   (a ~ MultiValue.Scalar v, MultiValue.PseudoModule v,
+    Marshal.C a, MultiValue.IntegerConstant a, Marshal.C v,
+    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize),
+    inp ~ MultiValue.T v, out ~ MultiValue.T v) =>
+      C (Cascade.ParameterValue n a) inp out where
+   type Input  (Cascade.ParameterValue n a) out = out
+   type Output (Cascade.ParameterValue n a) inp = inp
    process = Cascade.causal
 
 
 instance
-   (a ~ A.Scalar v, A.PseudoModule v, A.RationalConstant a,
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v,
     Memory.C a, Memory.C v) =>
       C (Allpass.Parameter a) v v where
    type Input  (Allpass.Parameter a) v = v
@@ -98,9 +119,8 @@
    process = Allpass.causal
 
 instance
-   (a ~ A.Scalar v, A.PseudoModule v, A.RationalConstant a,
-    Memory.C a, Memory.C v,
-    TypeNum.Natural n) =>
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v,
+    Memory.C a, Memory.C v, TypeNum.Natural n) =>
       C (Allpass.CascadeParameter n a) v v where
    type Input  (Allpass.CascadeParameter n a) v = v
    type Output (Allpass.CascadeParameter n a) v = v
@@ -108,7 +128,7 @@
 
 
 instance
-   (A.PseudoModule v, A.Scalar v ~ a, A.IntegerConstant a,
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v,
     Memory.C v, TypeNum.Natural n) =>
       C (Moog.Parameter n a) v v where
    type Input  (Moog.Parameter n a) v = v
@@ -117,7 +137,7 @@
 
 
 instance
-   (a ~ A.Scalar v, A.PseudoModule v, A.RationalConstant a,
+   (A.PseudoModule v, A.Scalar v ~ a, A.RationalConstant a,
     Memory.C a, Memory.C v) =>
       C (UniFilter.Parameter a) v (UniFilter.Result v) where
    type Input  (UniFilter.Parameter a) (UniFilter.Result v) = v
@@ -132,10 +152,9 @@
    process = ComplexFilt.causal
 
 instance
-   (Vector.Arithmetic a, IsConst a,
-    Memory.C (Value (Filt2P.State a))) =>
-      C (ComplexFiltPack.Parameter a)
-        (Stereo.T (Value a)) (Stereo.T (Value a)) where
-   type Input  (ComplexFiltPack.Parameter a) (Stereo.T (Value a)) = Stereo.T (Value a)
-   type Output (ComplexFiltPack.Parameter a) (Stereo.T (Value a)) = Stereo.T (Value a)
+   (Marshal.Vector n a, n ~ TypeNum.D3, MultiVector.PseudoRing a,
+    inp ~ MultiValue.T a, out ~ MultiValue.T a) =>
+      C (ComplexFiltPack.ParameterMV a) (Stereo.T inp) (Stereo.T out) where
+   type Input  (ComplexFiltPack.ParameterMV a) (Stereo.T out) = Stereo.T out
+   type Output (ComplexFiltPack.ParameterMV a) (Stereo.T inp) = Stereo.T inp
    process = ComplexFiltPack.causal
diff --git a/src/Synthesizer/LLVM/Causal/ControlledPacked.hs b/src/Synthesizer/LLVM/Causal/ControlledPacked.hs
--- a/src/Synthesizer/LLVM/Causal/ControlledPacked.hs
+++ b/src/Synthesizer/LLVM/Causal/ControlledPacked.hs
@@ -2,47 +2,73 @@
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE UndecidableInstances #-}
 {- |
-This is like "Synthesizer.LLVM.Causal.Controlled"
+This is like "Synthesizer.LLVM.CausalExp.Controlled"
 but for vectorised signals.
 -}
-module Synthesizer.LLVM.Causal.ControlledPacked (C(..)) where
+module Synthesizer.LLVM.Causal.ControlledPacked (
+   C(..),
+   processCtrlRate,
+   ) where
 
+import qualified Synthesizer.LLVM.Filter.SecondOrderCascade as Cascade
 import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
 import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1
 import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2
-import qualified Synthesizer.LLVM.Filter.SecondOrderCascade as Cascade
 import qualified Synthesizer.LLVM.Filter.Moog as Moog
 import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
 
-import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalS
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalP
 import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as Serial
 
+import Synthesizer.Causal.Class (($<))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Arithmetic as A
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core (IsSized)
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal.Number ((:*:))
 
+import qualified Algebra.Module as Module
+import qualified NumericPrelude.Numeric as NP
+
 import Control.Arrow ((<<<), arr, first)
 
 
+
+processCtrlRate ::
+   (C parameter av bv, Memory.C parameter,
+    Serial.Read  av, n ~ Serial.Size av,
+    Serial.Write bv, n ~ Serial.Size bv) =>
+   (Marshal.C r, MultiValue.RationalConstant r,
+    MultiValue.Field r, MultiValue.Comparison r) =>
+   Exp r -> (Exp r -> Sig.T parameter) -> Causal.T av bv
+processCtrlRate reduct ctrlGen = Serial.withSize $ \n ->
+   process $<
+      Sig.interpolateConstant (reduct / NP.fromIntegral n) (ctrlGen reduct)
+
+
 {- |
 A filter parameter type uniquely selects a filter function.
 However it does not uniquely determine the input and output type,
 since the same filter can run on mono and stereo signals.
 -}
-class (a ~ Input parameter b, b ~ Output parameter a) => C parameter a b where
-   type Input  parameter b :: *
-   type Output parameter a :: *
-   process :: (Causal.C process) => process (parameter, a) b
+class (Output parameter a ~ b, Input parameter b ~ a) => C parameter a b where
+   type Output parameter a
+   type Input  parameter b
+   process :: Causal.T (parameter, a) b
 
 
 {-
@@ -51,29 +77,29 @@
 -}
 
 instance
-   (Serial.C v, Serial.Element v ~ a,
-    A.PseudoRing a, A.IntegerConstant a, Memory.C a,
-    A.PseudoRing v) =>
+   (Serial.Write v, Serial.Element v ~ a,
+    A.PseudoRing v, A.IntegerConstant v,
+    A.PseudoRing a, A.IntegerConstant a, Expr.Aggregate ae a,
+    Tuple.Phi a, Tuple.Undefined a, Memory.C a) =>
       C (Filt1.Parameter a) v (Filt1.Result v) where
    type Input  (Filt1.Parameter a) (Filt1.Result v) = v
    type Output (Filt1.Parameter a) v = Filt1.Result v
    process = Filt1.causalPacked
 
 instance
-   (Serial.C v, Serial.Element v ~ a,
-    A.PseudoRing a, A.IntegerConstant a, Memory.C a,
-    A.PseudoRing v, A.IntegerConstant v, Memory.C v) =>
+   (Serial.Write v, Serial.Element v ~ a,
+    A.PseudoRing v, A.IntegerConstant v,
+    A.PseudoRing a, A.IntegerConstant a, Expr.Aggregate ae a,
+    Tuple.Phi a, Tuple.Undefined a, Memory.C a, Memory.C v) =>
       C (Filt2.Parameter a) v v where
    type Input  (Filt2.Parameter a) v = v
    type Output (Filt2.Parameter a) v = v
    process = Filt2.causalPacked
 
 instance
-   (LLVM.Value a ~ A.Scalar v, A.PseudoModule v,
-    Serial.C v, Serial.Element v ~ LLVM.Value a,
-    SoV.IntegerConstant a,
-    A.PseudoRing v, A.IntegerConstant v, Memory.C v,
-    LLVM.IsPrimitive a, IsSized a,
+   (Serial.Write v, Serial.Element v ~ MultiValue.T a,
+    Memory.C v, A.PseudoRing v, A.IntegerConstant v,
+    Marshal.C a, MultiValue.PseudoRing a, MultiValue.IntegerConstant a,
     TypeNum.Positive (n :*: LLVM.UnknownSize),
     TypeNum.Natural n) =>
       C (Cascade.ParameterValue n a) v v where
@@ -81,11 +107,10 @@
    type Output (Cascade.ParameterValue n a) v = v
    process = Cascade.causalPacked
 
-
 instance
-   (Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
+   (Serial.Write v, Serial.Element v ~ a,
+    A.PseudoRing a, A.IntegerConstant a, Memory.C a,
+    A.PseudoRing v, A.IntegerConstant v) =>
       C (Allpass.Parameter a) v v where
    type Input  (Allpass.Parameter a) v = v
    type Output (Allpass.Parameter a) v = v
@@ -93,7 +118,7 @@
 
 instance
    (TypeNum.Natural n,
-    Serial.C v, Serial.Element v ~ a,
+    Serial.Write v, Serial.Element v ~ a,
     A.PseudoRing a, A.IntegerConstant a, Memory.C a,
     A.PseudoRing v, A.RationalConstant v) =>
       C (Allpass.CascadeParameter n a) v v where
@@ -103,23 +128,22 @@
 
 
 instance
-   (Serial.C v, Serial.Element v ~ b, Tuple.Phi a, Tuple.Undefined a,
-    a ~ A.Scalar b, A.PseudoModule b, A.IntegerConstant a, Memory.C b,
-    TypeNum.Natural n) =>
+   (TypeNum.Natural n,
+    Serial.Write v, Serial.Element v ~ b, Memory.C b,
+    Tuple.Phi a, Tuple.Undefined a,
+    Expr.Aggregate ae a, Expr.Aggregate be b, Module.C ae be) =>
       C (Moog.Parameter n a) v v where
    type Input  (Moog.Parameter n a) v = v
    type Output (Moog.Parameter n a) v = v
-   process =
-      CausalS.pack Moog.causal <<<
-      first (arr Serial.constant)
+   process = CausalP.pack Moog.causal <<< first (arr Serial.constant)
 
 
 instance
-   (Serial.C v, Serial.Element v ~ b, Tuple.Phi a, Tuple.Undefined a,
-    a ~ A.Scalar b, A.PseudoModule b, A.IntegerConstant a, Memory.C b) =>
+   (Serial.Write v, Serial.Element v ~ b, Memory.C b,
+    Tuple.Phi a, Tuple.Undefined a,
+    Expr.Aggregate ae a, Expr.Aggregate be b, Module.C ae be) =>
       C (UniFilter.Parameter a) v (UniFilter.Result v) where
    type Input  (UniFilter.Parameter a) (UniFilter.Result v) = v
    type Output (UniFilter.Parameter a) v = UniFilter.Result v
    process =
-      CausalS.pack UniFilter.causal <<<
-      first (arr Serial.constant)
+      CausalP.pack UniFilter.causalExp <<< first (arr Serial.constant)
diff --git a/src/Synthesizer/LLVM/Causal/Exponential2.hs b/src/Synthesizer/LLVM/Causal/Exponential2.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/Exponential2.hs
@@ -0,0 +1,414 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{- |
+Exponential curve with controllable delay.
+-}
+module Synthesizer.LLVM.Causal.Exponential2 (
+   Parameter,
+   parameter,
+   parameterPlain,
+   multiValueParameter,
+   unMultiValueParameter,
+   causal,
+
+   ParameterPacked,
+   parameterPacked,
+   parameterPackedExp,
+   parameterPackedPlain,
+   multiValueParameterPacked,
+   unMultiValueParameterPacked,
+   causalPacked,
+   ) where
+
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Causal.Functional as F
+import qualified Synthesizer.LLVM.Frame.SerialVector.Plain as SerialPlain
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as SerialCode
+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as SerialOld
+import qualified Synthesizer.LLVM.Value as Value
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Marshal as MarshalMV
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.ScalarOrVector as SoV
+import qualified LLVM.Extra.Vector as Vector
+import qualified LLVM.Extra.Storable as Storable
+import qualified LLVM.Extra.Marshal as Marshal
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.Arithmetic as A
+
+import qualified LLVM.Core as LLVM
+import LLVM.Core (CodeGenFunction, Value, IsFloating)
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Foreign.Storable.Traversable as Store
+import qualified Foreign.Storable
+import Foreign.Storable (Storable)
+
+import qualified Control.Applicative as App
+import Control.Applicative (liftA2, pure, (<*>))
+import Control.Arrow (arr, (&&&))
+
+import qualified Data.Foldable as Fold
+import qualified Data.Traversable as Trav
+import Data.Traversable (traverse)
+
+import qualified Algebra.Transcendental as Trans
+
+import NumericPrelude.Numeric
+import NumericPrelude.Base
+
+
+newtype Parameter a = Parameter a
+   deriving (Show, Storable)
+
+
+instance Functor Parameter where
+   {-# INLINE fmap #-}
+   fmap f (Parameter k) = Parameter (f k)
+
+instance App.Applicative Parameter where
+   {-# INLINE pure #-}
+   pure x = Parameter x
+   {-# INLINE (<*>) #-}
+   Parameter f <*> Parameter k = Parameter (f k)
+
+instance Fold.Foldable Parameter where
+   {-# INLINE foldMap #-}
+   foldMap = Trav.foldMapDefault
+
+instance Trav.Traversable Parameter where
+   {-# INLINE sequenceA #-}
+   sequenceA (Parameter k) = fmap Parameter k
+
+
+instance (Tuple.Phi a) => Tuple.Phi (Parameter a) where
+   phi = Tuple.phiTraversable
+   addPhi = Tuple.addPhiFoldable
+
+instance Tuple.Undefined a => Tuple.Undefined (Parameter a) where
+   undef = Tuple.undefPointed
+
+instance Tuple.Zero a => Tuple.Zero (Parameter a) where
+   zero = Tuple.zeroPointed
+
+instance (Memory.C a) => Memory.C (Parameter a) where
+   type Struct (Parameter a) = Memory.Struct a
+   load = Memory.loadNewtype Parameter
+   store = Memory.storeNewtype (\(Parameter k) -> k)
+   decompose = Memory.decomposeNewtype Parameter
+   compose = Memory.composeNewtype (\(Parameter k) -> k)
+
+instance (Marshal.C a) => Marshal.C (Parameter a) where
+   pack (Parameter k) = Marshal.pack k
+   unpack = Parameter . Marshal.unpack
+
+instance (MarshalMV.C a) => MarshalMV.C (Parameter a) where
+   pack (Parameter k) = MarshalMV.pack k
+   unpack = Parameter . MarshalMV.unpack
+
+instance (Storable.C a) => Storable.C (Parameter a) where
+   load = Storable.loadNewtype Parameter Parameter
+   store = Storable.storeNewtype Parameter (\(Parameter k) -> k)
+
+instance (Tuple.Value a) => Tuple.Value (Parameter a) where
+   type ValueOf (Parameter a) = Parameter (Tuple.ValueOf a)
+   valueOf = Tuple.valueOfFunctor
+
+instance (MultiValue.C a) => MultiValue.C (Parameter a) where
+   type Repr (Parameter a) = Parameter (MultiValue.Repr a)
+   cons = multiValueParameter . fmap MultiValue.cons
+   undef = multiValueParameter $ pure MultiValue.undef
+   zero = multiValueParameter $ pure MultiValue.zero
+   phi bb =
+      fmap multiValueParameter .
+      traverse (MultiValue.phi bb) . unMultiValueParameter
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb)
+         (unMultiValueParameter a) (unMultiValueParameter b)
+
+multiValueParameter ::
+   Parameter (MultiValue.T a) -> MultiValue.T (Parameter a)
+multiValueParameter = MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
+
+unMultiValueParameter ::
+   MultiValue.T (Parameter a) -> Parameter (MultiValue.T a)
+unMultiValueParameter (MultiValue.Cons x) = fmap MultiValue.Cons x
+
+
+instance (Value.Flatten a) => Value.Flatten (Parameter a) where
+   type Registers (Parameter a) = Parameter (Value.Registers a)
+   flattenCode = Value.flattenCodeTraversable
+   unfoldCode = Value.unfoldCodeTraversable
+
+
+instance (Vector.Simple v) => Vector.Simple (Parameter v) where
+   type Element (Parameter v) = Parameter (Vector.Element v)
+   type Size (Parameter v) = Vector.Size v
+   shuffleMatch = Vector.shuffleMatchTraversable
+   extract = Vector.extractTraversable
+
+instance (Vector.C v) => Vector.C (Parameter v) where
+   insert  = Vector.insertTraversable
+
+
+instance
+   (Expr.Aggregate exp mv) =>
+      Expr.Aggregate (Parameter exp) (Parameter mv) where
+   type MultiValuesOf (Parameter exp) = Parameter (Expr.MultiValuesOf exp)
+   type ExpressionsOf (Parameter mv) = Parameter (Expr.ExpressionsOf mv)
+   bundle (Parameter p) = fmap Parameter $ Expr.bundle p
+   dissect (Parameter p) = Parameter $ Expr.dissect p
+
+
+parameter ::
+   (Trans.C a, SoV.TranscendentalConstant a, IsFloating a) =>
+   Value a ->
+   CodeGenFunction r (Parameter (Value a))
+parameter = Value.unlift1 parameterPlain
+
+parameterPlain ::
+   (Trans.C a) =>
+   a -> Parameter a
+parameterPlain halfLife =
+   Parameter $ 0.5 ^? recip halfLife
+
+
+causal ::
+   (MarshalMV.C a, MultiValue.T a ~ am, MultiValue.PseudoRing a) =>
+   Exp a -> Causal.T (Parameter am) am
+causal initial =
+   Causal.loop initial
+      (arr snd &&& CausalPriv.zipWith (\(Parameter a) -> A.mul a))
+
+
+data ParameterPacked a =
+   ParameterPacked {ppFeedback, ppCurrent :: a}
+
+
+instance Functor ParameterPacked where
+   {-# INLINE fmap #-}
+   fmap f p = ParameterPacked
+      (f $ ppFeedback p) (f $ ppCurrent p)
+
+instance App.Applicative ParameterPacked where
+   {-# INLINE pure #-}
+   pure x = ParameterPacked x x
+   {-# INLINE (<*>) #-}
+   f <*> p = ParameterPacked
+      (ppFeedback f $ ppFeedback p)
+      (ppCurrent f $ ppCurrent p)
+
+instance Fold.Foldable ParameterPacked where
+   {-# INLINE foldMap #-}
+   foldMap = Trav.foldMapDefault
+
+instance Trav.Traversable ParameterPacked where
+   {-# INLINE sequenceA #-}
+   sequenceA p =
+      liftA2 ParameterPacked
+         (ppFeedback p) (ppCurrent p)
+
+
+instance (Tuple.Phi a) => Tuple.Phi (ParameterPacked a) where
+   phi = Tuple.phiTraversable
+   addPhi = Tuple.addPhiFoldable
+
+instance Tuple.Undefined a => Tuple.Undefined (ParameterPacked a) where
+   undef = Tuple.undefPointed
+
+instance Tuple.Zero a => Tuple.Zero (ParameterPacked a) where
+   zero = Tuple.zeroPointed
+
+
+{-
+storeParameter ::
+   Storable a => Store.Dictionary (ParameterPacked a)
+storeParameter =
+   Store.run $
+   liftA2 ParameterPacked
+      (Store.element ppFeedback)
+      (Store.element ppCurrent)
+
+instance Storable a => Storable (ParameterPacked a) where
+   sizeOf    = Store.sizeOf storeParameter
+   alignment = Store.alignment storeParameter
+   peek      = Store.peek storeParameter
+   poke      = Store.poke storeParameter
+-}
+
+instance Storable a => Storable (ParameterPacked a) where
+   sizeOf    = Store.sizeOf
+   alignment = Store.alignment
+   peek      = Store.peekApplicative
+   poke      = Store.poke
+
+
+type ParameterPackedStruct a = LLVM.Struct (a, (a, ()))
+
+memory ::
+   (Memory.C a) =>
+   Memory.Record r (ParameterPackedStruct (Memory.Struct a)) (ParameterPacked a)
+memory =
+   liftA2 ParameterPacked
+      (Memory.element ppFeedback TypeNum.d0)
+      (Memory.element ppCurrent  TypeNum.d1)
+
+instance (Memory.C a) => Memory.C (ParameterPacked a) where
+   type Struct (ParameterPacked a) = ParameterPackedStruct (Memory.Struct a)
+   load = Memory.loadRecord memory
+   store = Memory.storeRecord memory
+   decompose = Memory.decomposeRecord memory
+   compose = Memory.composeRecord memory
+
+instance (Marshal.C a) => Marshal.C (ParameterPacked a) where
+   pack (ParameterPacked bend depth) = Marshal.pack (bend, depth)
+   unpack = uncurry ParameterPacked . Marshal.unpack
+
+instance (MarshalMV.C a) => MarshalMV.C (ParameterPacked a) where
+   pack (ParameterPacked bend depth) = MarshalMV.pack (bend, depth)
+   unpack = uncurry ParameterPacked . MarshalMV.unpack
+
+instance (Storable.C a) => Storable.C (ParameterPacked a) where
+   load = Storable.loadApplicative
+   store = Storable.storeFoldable
+
+
+instance (Tuple.Value a) => Tuple.Value (ParameterPacked a) where
+   type ValueOf (ParameterPacked a) = ParameterPacked (Tuple.ValueOf a)
+   valueOf = Tuple.valueOfFunctor
+
+instance (MultiValue.C a) => MultiValue.C (ParameterPacked a) where
+   type Repr (ParameterPacked a) = ParameterPacked (MultiValue.Repr a)
+   cons = multiValueParameterPacked . fmap MultiValue.cons
+   undef = multiValueParameterPacked $ pure MultiValue.undef
+   zero = multiValueParameterPacked $ pure MultiValue.zero
+   phi bb =
+      fmap multiValueParameterPacked .
+      traverse (MultiValue.phi bb) . unMultiValueParameterPacked
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb)
+         (unMultiValueParameterPacked a) (unMultiValueParameterPacked b)
+
+multiValueParameterPacked ::
+   ParameterPacked (MultiValue.T a) -> MultiValue.T (ParameterPacked a)
+multiValueParameterPacked = MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
+
+unMultiValueParameterPacked ::
+   MultiValue.T (ParameterPacked a) -> ParameterPacked (MultiValue.T a)
+unMultiValueParameterPacked (MultiValue.Cons x) = fmap MultiValue.Cons x
+
+
+instance (Value.Flatten a) => Value.Flatten (ParameterPacked a) where
+   type Registers (ParameterPacked a) = ParameterPacked (Value.Registers a)
+   flattenCode = Value.flattenCodeTraversable
+   unfoldCode = Value.unfoldCodeTraversable
+
+instance
+   (Expr.Aggregate exp mv) =>
+      Expr.Aggregate (ParameterPacked exp) (ParameterPacked mv) where
+   type MultiValuesOf (ParameterPacked exp) =
+            ParameterPacked (Expr.MultiValuesOf exp)
+   type ExpressionsOf (ParameterPacked mv) =
+            ParameterPacked (Expr.ExpressionsOf mv)
+   bundle p =
+      liftA2 ParameterPacked
+         (Expr.bundle $ ppFeedback p) (Expr.bundle $ ppCurrent p)
+   dissect p =
+      ParameterPacked
+         (Expr.dissect $ ppFeedback p) (Expr.dissect $ ppCurrent p)
+
+
+type instance F.Arguments f (ParameterPacked a) = f (ParameterPacked a)
+instance F.MakeArguments (ParameterPacked a) where
+   makeArgs = id
+
+
+
+withSize ::
+   (TypeNum.Natural n) =>
+   (SerialOld.Write v, SerialOld.Size v ~ n, TypeNum.Positive n) =>
+   (TypeNum.Singleton n -> m (param v)) ->
+   m (param v)
+withSize f = f TypeNum.singleton
+
+parameterPacked ::
+   (SerialOld.Write v, SerialOld.Element v ~ a,
+    A.PseudoRing v, A.RationalConstant v,
+    A.Transcendental a, A.RationalConstant a) =>
+   a -> CodeGenFunction r (ParameterPacked v)
+parameterPacked halfLife = withSize $ \n -> do
+   feedback <-
+      SerialOld.upsample =<<
+      A.pow (A.fromRational' 0.5) =<<
+      A.fdiv (A.fromInteger' $ TypeNum.integralFromSingleton n) halfLife
+   k <-
+      A.pow (A.fromRational' 0.5) =<<
+      A.fdiv (A.fromInteger' 1) halfLife
+   current <-
+      SerialOld.iterate (A.mul k) (A.fromInteger' 1)
+   return $ ParameterPacked feedback current
+{-
+   Value.unlift1 parameterPackedPlain
+-}
+
+withSizePlain ::
+   (TypeNum.Positive n) =>
+   (TypeNum.Singleton n -> param (Serial.T n a)) ->
+   param (Serial.T n a)
+withSizePlain f = f TypeNum.singleton
+
+parameterPackedPlain ::
+   (TypeNum.Positive n, Trans.C a) =>
+   a -> ParameterPacked (Serial.T n a)
+parameterPackedPlain halfLife =
+   withSizePlain $ \n ->
+   ParameterPacked
+      (SerialPlain.replicate
+         (0.5 ^? (fromInteger (TypeNum.integerFromSingleton n) / halfLife)))
+      (SerialPlain.iterate (0.5 ^? recip halfLife *) one)
+
+withSizeExp ::
+   (TypeNum.Positive n) =>
+   (TypeNum.Singleton n -> param (exp (Serial.T n a))) ->
+   param (exp (Serial.T n a))
+withSizeExp f = f TypeNum.singleton
+
+parameterPackedExp ::
+   (TypeNum.Positive n) =>
+   (MultiValue.Transcendental a, MultiValue.RationalConstant a) =>
+   (MultiVector.C a) =>
+   Exp a -> ParameterPacked (Exp (Serial.T n a))
+parameterPackedExp halfLife =
+   withSizeExp $ \n ->
+   ParameterPacked
+      (Serial.upsample
+         (0.5 ^? (fromInteger (TypeNum.integerFromSingleton n) / halfLife)))
+      (Serial.iterate (0.5 ^? recip halfLife *) one)
+
+
+causalPacked ::
+   (MultiVector.PseudoRing a, MultiValue.IntegerConstant a,
+    TypeNum.Positive n, MarshalMV.Vector n a, MarshalMV.C a) =>
+   Exp a ->
+   Causal.T (ParameterPacked (SerialCode.Value n a)) (SerialCode.Value n a)
+causalPacked initial =
+   Causal.loop
+      (Serial.upsample initial)
+      (CausalPriv.map $
+       \(p, s0) -> liftA2 (,)
+          (A.mul (ppCurrent p) s0)
+          (A.mul (ppFeedback p) s0))
diff --git a/src/Synthesizer/LLVM/Causal/Functional.hs b/src/Synthesizer/LLVM/Causal/Functional.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/Functional.hs
@@ -0,0 +1,519 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Causal.Functional (
+   T,
+   lift, fromSignal,
+   ($&), (&|&),
+   compile,
+   compileSignal,
+   withArgs, MakeArguments, Arguments, makeArgs,
+   AnyArg(..),
+
+   Ground(Ground),
+   withGroundArgs, MakeGroundArguments, GroundArguments,
+   makeGroundArgs,
+
+   Atom(..), atom,
+   withGuidedArgs, MakeGuidedArguments, GuidedArguments, PatternArguments,
+   makeGuidedArgs,
+
+   PrepareArguments(PrepareArguments), withPreparedArgs, withPreparedArgs2,
+   atomArg, stereoArgs, pairArgs, tripleArgs,
+   ) where
+
+import qualified Synthesizer.LLVM.Causal.Private as CausalCore
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Signal as Signal
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as Serial
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.Causal.Class as CausalClass
+import Synthesizer.LLVM.Private (getPairPtrs, noLocalPtr)
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Arithmetic as A
+
+import LLVM.Core (CodeGenFunction)
+import qualified LLVM.Core as LLVM
+
+import qualified Number.Ratio as Ratio
+import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Algebraic as Algebraic
+import qualified Algebra.Field as Field
+import qualified Algebra.Ring as Ring
+import qualified Algebra.Additive as Additive
+
+import qualified Control.Monad.Trans.State as State
+import qualified Control.Monad.Trans.Class as MT
+import Control.Monad.Trans.State (StateT)
+
+import qualified Data.Vault.Lazy as Vault
+import Data.Vault.Lazy (Vault)
+import qualified Control.Category as Cat
+import Control.Arrow (Arrow, (>>^), (&&&), arr, first)
+import Control.Category (Category, (.))
+import Control.Applicative (Applicative, (<*>), pure, liftA2)
+
+import Data.Tuple.Strict (zipPair)
+import Data.Tuple.HT (fst3, snd3, thd3)
+
+import qualified System.Unsafe as Unsafe
+
+import Prelude hiding ((.))
+
+
+newtype T inp out = Cons (Code inp out)
+
+
+-- | similar to @Causal.T a b@
+data Code a b =
+   forall global local state.
+      (Memory.C global, LLVM.IsSized local, Memory.C state) =>
+      Code (forall r c.
+            (Tuple.Phi c) =>
+            global -> LLVM.Value (LLVM.Ptr local) -> a -> state ->
+            StateT Vault (MaybeCont.T r c) (b, state))
+               -- compute next value
+           (forall r. CodeGenFunction r (global, state))
+               -- initial state
+           (forall r. global -> CodeGenFunction r ())
+               -- cleanup
+
+
+instance Category Code where
+   id = arr id
+   Code nextB startB stopB . Code nextA startA stopA = Code
+      (\(globalA, globalB) local a (sa0,sb0) -> do
+         (localA,localB) <- MT.lift $ getPairPtrs local
+         (b,sa1) <- nextA globalA localA a sa0
+         (c,sb1) <- nextB globalB localB b sb0
+         return (c, (sa1,sb1)))
+      (liftA2 zipPair startA startB)
+      (\(globalA, globalB) -> stopA globalA >> stopB globalB)
+
+
+instance Arrow Code where
+   arr f = Code
+      (\() -> noLocalPtr $ \a () -> return (f a, ()))
+      (return ((),()))
+      (\() -> return ())
+   first (Code next start stop) = Code (CausalCore.firstNext next) start stop
+
+
+{-
+We must not define Category and Arrow instances
+because in osci***osci the result of osci would be shared,
+although it depends on the particular input.
+
+instance Category T where
+   id = tagUnique Cat.id
+   Cons a . Cons b = tagUnique (a . b)
+
+instance Arrow T where
+   arr f = tagUnique $ arr f
+   first (Cons a) = tagUnique $ first a
+-}
+
+instance Functor (T inp) where
+   fmap f (Cons x) =
+      tagUnique $ x >>^ f
+
+instance Applicative (T inp) where
+   pure a = tagUnique $ arr (const a)
+   f <*> x = fmap (uncurry ($))  $  f &|& x
+
+
+lift0 :: (forall r. CodeGenFunction r out) -> T inp out
+lift0 f = lift (CausalCore.map (const f))
+
+lift1 :: (forall r. a -> CodeGenFunction r out) -> T inp a -> T inp out
+lift1 f x = CausalCore.map f $& x
+
+lift2 ::
+   (forall r. a -> b -> CodeGenFunction r out) ->
+   T inp a -> T inp b -> T inp out
+lift2 f x y = CausalCore.zipWith f $& x&|&y
+
+
+instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => Num (T a b) where
+   fromInteger n = pure (A.fromInteger' n)
+   (+) = lift2 A.add
+   (-) = lift2 A.sub
+   (*) = lift2 A.mul
+   abs = lift1 A.abs
+   signum = lift1 A.signum
+
+instance (A.Field b, A.Real b, A.RationalConstant b) => Fractional (T a b) where
+   fromRational x = pure (A.fromRational' x)
+   (/) = lift2 A.fdiv
+
+
+instance (A.Additive b) => Additive.C (T a b) where
+   zero = pure A.zero
+   (+) = lift2 A.add
+   (-) = lift2 A.sub
+   negate = lift1 A.neg
+
+instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T a b) where
+   one = pure A.one
+   fromInteger n = pure (A.fromInteger' n)
+   (*) = lift2 A.mul
+
+instance (A.Field b, A.RationalConstant b) => Field.C (T a b) where
+   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
+   (/) = lift2 A.fdiv
+
+instance (A.Transcendental b, A.RationalConstant b) => Algebraic.C (T a b) where
+   sqrt = lift1 A.sqrt
+   root n x = lift2 A.pow x (Field.recip $ Ring.fromInteger n)
+   x^/r = lift2 A.pow x (Field.fromRational' r)
+
+instance (A.Transcendental b, A.RationalConstant b) => Trans.C (T a b) where
+   pi = lift0 A.pi
+   sin = lift1 A.sin
+   cos = lift1 A.cos
+   (**) = lift2 A.pow
+   exp = lift1 A.exp
+   log = lift1 A.log
+
+   asin _ = error "LLVM missing intrinsic: asin"
+   acos _ = error "LLVM missing intrinsic: acos"
+   atan _ = error "LLVM missing intrinsic: atan"
+
+
+infixr 0 $&
+
+($&) :: Causal.T b c -> T a b -> T a c
+f $& (Cons b) =
+   tagUnique $  liftCode f . b
+
+
+infixr 3 &|&
+
+(&|&) :: T a b -> T a c -> T a (b,c)
+Cons b &|& Cons c =
+   tagUnique $  b &&& c
+
+
+liftCode :: Causal.T inp out -> Code inp out
+liftCode (CausalCore.Cons next start stop) =
+   Code
+      (\p l a state -> MT.lift (next p l a state))
+      start stop
+
+lift :: Causal.T inp out -> T inp out
+lift = tagUnique . liftCode
+
+fromSignal :: Signal.T out -> T inp out
+fromSignal = lift . CausalClass.fromSignal
+
+tag :: Vault.Key out -> Code inp out -> T inp out
+tag key (Code next start stop) =
+   Cons $
+   Code
+      (\p l a s0 -> do
+         mb <- State.gets (Vault.lookup key)
+         case mb of
+            Just b -> return (b,s0)
+            Nothing -> do
+               bs@(b,_) <- next p l a s0
+               State.modify (Vault.insert key b)
+               return bs)
+      start stop
+
+-- dummy for debugging
+_tag :: Vault.Key out -> Code inp out -> T inp out
+_tag _ = Cons
+
+tagUnique :: Code inp out -> T inp out
+tagUnique code =
+   Unsafe.performIO $
+   fmap (flip tag code) Vault.newKey
+
+initialize :: Code inp out -> Causal.T inp out
+initialize (Code next start stop) =
+   CausalCore.Cons
+      (\p l a state -> State.evalStateT (next p l a state) Vault.empty)
+      start stop
+
+compile :: T inp out -> Causal.T inp out
+compile (Cons code) = initialize code
+
+compileSignal :: T () out -> Signal.T out
+compileSignal f = CausalClass.toSignal $ compile f
+
+
+{- |
+Using 'withArgs' you can simplify
+
+> let x = F.lift (arr fst)
+>     y = F.lift (arr (fst.snd))
+>     z = F.lift (arr (snd.snd))
+> in  F.compile (f x y z)
+
+to
+
+> withArgs $ \(x,(y,z)) -> f x y z
+-}
+withArgs ::
+   (MakeArguments inp) =>
+   (Arguments (T inp) inp -> T inp out) -> Causal.T inp out
+withArgs f = withId $ f . makeArgs
+
+withId :: (T inp inp -> T inp out) -> Causal.T inp out
+withId f = compile $ f $ lift Cat.id
+
+
+type family Arguments (f :: * -> *) arg
+
+class MakeArguments arg where
+   makeArgs :: Functor f => f arg -> Arguments f arg
+
+
+{-
+I have thought about an Arg type, that marks where to stop descending.
+This way we can throw away all of these FlexibleContext instances
+and the user can freely choose the granularity of arguments.
+However this does not work so easily,
+because we would need a functional depedency from, say,
+@(Arg a, Arg b)@ to @(a,b)@.
+This is the opposite direction to the dependency we use currently.
+The 'AnyArg' type provides a solution in this spirit.
+-}
+type instance Arguments f (LLVM.Value a) = f (LLVM.Value a)
+instance MakeArguments (LLVM.Value a) where
+   makeArgs = id
+
+type instance Arguments f (MultiValue.T a) = f (MultiValue.T a)
+instance MakeArguments (MultiValue.T a) where
+   makeArgs = id
+
+{- |
+Consistent with pair instance.
+You may use 'AnyArg' or 'withGuidedArgs'
+to stop descending into the stereo channels.
+-}
+type instance Arguments f (Stereo.T a) = Stereo.T (Arguments f a)
+instance (MakeArguments a) => MakeArguments (Stereo.T a) where
+   makeArgs = fmap makeArgs . Stereo.sequence
+
+type instance Arguments f (Serial.Constant n a) = f (Serial.Constant n a)
+instance MakeArguments (Serial.Constant n a) where
+   makeArgs = id
+
+type instance Arguments f () = f ()
+instance MakeArguments () where
+   makeArgs = id
+
+type instance Arguments f (a,b) = (Arguments f a, Arguments f b)
+instance (MakeArguments a, MakeArguments b) =>
+      MakeArguments (a,b) where
+   makeArgs f = (makeArgs $ fmap fst f, makeArgs $ fmap snd f)
+
+type instance Arguments f (a,b,c) =
+                  (Arguments f a, Arguments f b, Arguments f c)
+instance (MakeArguments a, MakeArguments b, MakeArguments c) =>
+      MakeArguments (a,b,c) where
+   makeArgs f =
+      (makeArgs $ fmap fst3 f, makeArgs $ fmap snd3 f, makeArgs $ fmap thd3 f)
+
+
+{- |
+You can use this to explicitly stop breaking of composed data types.
+It might be more comfortable to do this using 'withGuidedArgs'.
+-}
+newtype AnyArg a = AnyArg {getAnyArg :: a}
+
+type instance Arguments f (AnyArg a) = f a
+instance MakeArguments (AnyArg a) where
+   makeArgs = fmap getAnyArg
+
+
+
+{- |
+This is similar to 'withArgs'
+but it requires to specify the decomposition depth
+using constructors in the arguments.
+-}
+withGroundArgs ::
+   (MakeGroundArguments (T inp) args,
+    GroundArguments args ~ inp) =>
+   (args -> T inp out) -> Causal.T inp out
+withGroundArgs f = withId $ f . makeGroundArgs
+
+
+newtype Ground f a = Ground (f a)
+
+
+type family GroundArguments args
+
+class (Functor f) => MakeGroundArguments f args where
+   makeGroundArgs :: f (GroundArguments args) -> args
+
+
+type instance GroundArguments (Ground f a) = a
+instance (Functor f, f ~ g) => MakeGroundArguments f (Ground g a) where
+   makeGroundArgs = Ground
+
+type instance GroundArguments (Stereo.T a) = Stereo.T (GroundArguments a)
+instance MakeGroundArguments f a => MakeGroundArguments f (Stereo.T a) where
+   makeGroundArgs f =
+      Stereo.cons
+         (makeGroundArgs $ fmap Stereo.left f)
+         (makeGroundArgs $ fmap Stereo.right f)
+
+type instance GroundArguments () = ()
+instance (Functor f) => MakeGroundArguments f () where
+   makeGroundArgs _ = ()
+
+
+type instance
+   GroundArguments (a,b) =
+      (GroundArguments a, GroundArguments b)
+instance
+   (MakeGroundArguments f a, MakeGroundArguments f b) =>
+      MakeGroundArguments f (a,b) where
+   makeGroundArgs f =
+      (makeGroundArgs $ fmap fst f,
+       makeGroundArgs $ fmap snd f)
+
+type instance
+   GroundArguments (a,b,c) =
+      (GroundArguments a, GroundArguments b, GroundArguments c)
+instance
+   (MakeGroundArguments f a, MakeGroundArguments f b,
+    MakeGroundArguments f c) =>
+      MakeGroundArguments f (a,b,c) where
+   makeGroundArgs f =
+      (makeGroundArgs $ fmap fst3 f,
+       makeGroundArgs $ fmap snd3 f,
+       makeGroundArgs $ fmap thd3 f)
+
+
+
+{- |
+This is similar to 'withArgs'
+but it allows to specify the decomposition depth using a pattern.
+-}
+withGuidedArgs ::
+   (MakeGuidedArguments pat, PatternArguments pat ~ inp) =>
+   pat ->
+   (GuidedArguments (T inp) pat -> T inp out) -> Causal.T inp out
+withGuidedArgs p f = withId $ f . makeGuidedArgs p
+
+
+data Atom a = Atom
+
+atom :: Atom a
+atom = Atom
+
+
+type family GuidedArguments (f :: * -> *) pat
+type family PatternArguments pat
+
+class MakeGuidedArguments pat where
+   makeGuidedArgs ::
+      Functor f =>
+      pat -> f (PatternArguments pat) -> GuidedArguments f pat
+
+
+type instance GuidedArguments f (Atom a) = f a
+type instance PatternArguments (Atom a) = a
+instance MakeGuidedArguments (Atom a) where
+   makeGuidedArgs Atom = id
+
+type instance GuidedArguments f (Stereo.T a) = Stereo.T (GuidedArguments f a)
+type instance PatternArguments (Stereo.T a) = Stereo.T (PatternArguments a)
+instance MakeGuidedArguments a => MakeGuidedArguments (Stereo.T a) where
+   makeGuidedArgs pat f =
+      Stereo.cons
+         (makeGuidedArgs (Stereo.left  pat) $ fmap Stereo.left f)
+         (makeGuidedArgs (Stereo.right pat) $ fmap Stereo.right f)
+
+type instance GuidedArguments f () = f ()
+type instance PatternArguments () = ()
+instance MakeGuidedArguments () where
+   makeGuidedArgs () = id
+
+type instance
+   GuidedArguments f (a,b) =
+      (GuidedArguments f a, GuidedArguments f b)
+type instance
+   PatternArguments (a,b) =
+      (PatternArguments a, PatternArguments b)
+instance (MakeGuidedArguments a, MakeGuidedArguments b) =>
+      MakeGuidedArguments (a,b) where
+   makeGuidedArgs (pa,pb) f =
+      (makeGuidedArgs pa $ fmap fst f,
+       makeGuidedArgs pb $ fmap snd f)
+
+type instance
+   GuidedArguments f (a,b,c) =
+      (GuidedArguments f a, GuidedArguments f b, GuidedArguments f c)
+type instance
+   PatternArguments (a,b,c) =
+      (PatternArguments a, PatternArguments b, PatternArguments c)
+instance
+   (MakeGuidedArguments a, MakeGuidedArguments b, MakeGuidedArguments c) =>
+      MakeGuidedArguments (a,b,c) where
+   makeGuidedArgs (pa,pb,pc) f =
+      (makeGuidedArgs pa $ fmap fst3 f,
+       makeGuidedArgs pb $ fmap snd3 f,
+       makeGuidedArgs pc $ fmap thd3 f)
+
+
+
+{- |
+Alternative to withGuidedArgs.
+This way of pattern construction is even Haskell 98.
+-}
+withPreparedArgs ::
+   PrepareArguments (T inp) inp a ->
+   (a -> T inp out) -> Causal.T inp out
+withPreparedArgs (PrepareArguments prepare) f = withId $ f . prepare
+
+withPreparedArgs2 ::
+   PrepareArguments (T (inp0, inp1)) inp0 a ->
+   PrepareArguments (T (inp0, inp1)) inp1 b ->
+   (a -> b -> T (inp0, inp1) out) ->
+   Causal.T (inp0, inp1) out
+withPreparedArgs2 prepareA prepareB f =
+   withPreparedArgs (pairArgs prepareA prepareB) (uncurry f)
+
+newtype PrepareArguments f merged separated =
+   PrepareArguments (f merged -> separated)
+
+atomArg :: PrepareArguments f a (f a)
+atomArg = PrepareArguments id
+
+stereoArgs ::
+   (Functor f) =>
+   PrepareArguments f a b ->
+   PrepareArguments f (Stereo.T a) (Stereo.T b)
+stereoArgs (PrepareArguments p) =
+   PrepareArguments $ fmap p . Stereo.sequence
+
+pairArgs ::
+   (Functor f) =>
+   PrepareArguments f a0 b0 ->
+   PrepareArguments f a1 b1 ->
+   PrepareArguments f (a0,a1) (b0,b1)
+pairArgs (PrepareArguments p0) (PrepareArguments p1) =
+   PrepareArguments $ \f -> (p0 $ fmap fst f, p1 $ fmap snd f)
+
+tripleArgs ::
+   (Functor f) =>
+   PrepareArguments f a0 b0 ->
+   PrepareArguments f a1 b1 ->
+   PrepareArguments f a2 b2 ->
+   PrepareArguments f (a0,a1,a2) (b0,b1,b2)
+tripleArgs (PrepareArguments p0) (PrepareArguments p1) (PrepareArguments p2) =
+   PrepareArguments $ \f ->
+      (p0 $ fmap fst3 f, p1 $ fmap snd3 f, p2 $ fmap thd3 f)
diff --git a/src/Synthesizer/LLVM/Causal/FunctionalPlug.hs b/src/Synthesizer/LLVM/Causal/FunctionalPlug.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/FunctionalPlug.hs
@@ -0,0 +1,376 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE FlexibleContexts #-}
+module Synthesizer.LLVM.Causal.FunctionalPlug (
+   T,
+   ($&), (&|&),
+   run, runPlugOut,
+   fromSignal, plug, askParameter, Input,
+   withArgs, withArgsPlugOut,
+   MakeArguments, Arguments, makeArgs,
+   ) where
+
+import qualified Synthesizer.LLVM.Plug.Input as PIn
+import qualified Synthesizer.LLVM.Plug.Output as POut
+
+import qualified Synthesizer.LLVM.Causal.Parameterized as Parameterized
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+
+import qualified Synthesizer.Causal.Class as CausalClass
+import qualified Synthesizer.CausalIO.Process as PIO
+import qualified Synthesizer.Generic.Cut as CutG
+import qualified Synthesizer.Zip as Zip
+
+import qualified Data.EventList.Relative.BodyTime as EventListBT
+import qualified Data.StorableVector as SV
+
+import LLVM.DSL.Expression (Exp(Exp))
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Arithmetic as A
+import LLVM.Core (CodeGenFunction)
+
+import Data.IORef (newIORef, readIORef)
+
+import qualified Number.Ratio as Ratio
+import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Algebraic as Algebraic
+import qualified Algebra.Field as Field
+import qualified Algebra.Ring as Ring
+import qualified Algebra.Additive as Additive
+
+import qualified Control.Monad.Trans.Reader as MR
+import qualified Control.Monad.Trans.State as MS
+import Control.Monad.IO.Class (liftIO)
+
+import qualified Data.Set as Set
+import qualified Data.Vault.Lazy as Vault
+import Data.Vault.Lazy (Vault)
+import Data.Unique (Unique, newUnique)
+import Data.Maybe (fromMaybe)
+
+import Control.Arrow ((^<<), (<<^), arr, first, second)
+import Control.Category (id, (.))
+import Control.Applicative (Applicative, (<*>), pure, liftA2, liftA3)
+
+import qualified System.Unsafe as Unsafe
+
+import Prelude hiding (id, (.))
+
+
+{- |
+This data type detects sharing.
+-}
+{-
+There are two levels of the use of keys.
+At the top level, in T's State monad,
+we store an object id in order to check,
+whether we have already seen a certain object.
+If we encounter a known object
+then we use the Simple constructor
+and fetch the stored CausalP output
+within the causal process enclosed in Simple.
+This and the causal process in the Plugged constructor
+are the second level.
+These arrows handle a Vault like a state monad
+and insert all values they produce into the Vault.
+-}
+newtype T pp inp out =
+   Cons (MS.State (Set.Set Unique) (Core pp inp out))
+
+{-
+We need to hide the x and y types
+since these types grow when combining Cores,
+and then we could not define numeric instances.
+-}
+data Core pp inp out =
+   forall x y. CutG.Read x =>
+   Plugged
+      (pp -> inp -> x)
+      (PIn.T x y)
+      (Causal.T (y, Vault) (out, Vault))
+   |
+   {-
+   The Simple constructor is needed for reusing shared CausalP processes
+   and for input without external representation. (a Plug.Input)
+   -}
+   Simple (Causal.T Vault (out, Vault))
+
+
+applyCore ::
+   Causal.T (a, Vault) (b, Vault) ->
+   Core pp inp a ->
+   Core pp inp b
+applyCore f core =
+   case core of
+      Plugged prep plg process -> Plugged prep plg (f . process)
+      Simple process -> Simple (f . process)
+
+combineCore ::
+   Core pp inp a ->
+   Core pp inp b ->
+   Core pp inp (a,b)
+combineCore (Plugged prepA plugA processA) (Plugged prepB plugB processB) =
+   Plugged
+      (\p -> Zip.arrowFanout (prepA p) (prepB p))
+      (PIn.split plugA plugB)
+      ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB
+       . arr (\((a,v),b) -> (a,(b,v))) .
+       first processA <<^ (\((a,b),v) -> ((a,v),b)))
+combineCore (Simple processA) (Plugged prepB plugB processB) =
+   Plugged prepB plugB
+      ((\(b,(a,v)) -> ((a,b), v)) ^<< second processA . processB)
+combineCore (Plugged prepA plugA processA) (Simple processB) =
+   Plugged prepA plugA
+      ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB . processA)
+combineCore (Simple processA) (Simple processB) =
+   Simple ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB . processA)
+
+
+reuseCore :: Vault.Key out -> Core pp inp out
+reuseCore key =
+   Simple $ arr $ \vault ->
+      (fromMaybe (error "key must have been lost") $ Vault.lookup key vault,
+       vault)
+
+
+tag ::
+   Unique -> Vault.Key out ->
+   MS.State (Set.Set Unique) (Core pp inp out) ->
+   T pp inp out
+tag unique key stateCore = Cons $ do
+   alreadySeen <- MS.gets (Set.member unique)
+   if alreadySeen
+      then return $ reuseCore key
+      else do
+         MS.modify (Set.insert unique)
+         fmap (applyCore (arr $ \(a,v) -> (a, Vault.insert key a v))) stateCore
+
+tagUnique ::
+   MS.State (Set.Set Unique) (Core pp inp out) ->
+   T pp inp out
+tagUnique core =
+   Unsafe.performIO $
+   liftA3 tag newUnique Vault.newKey (pure core)
+
+
+infixr 0 $&
+
+($&) ::
+   Causal.T a b ->
+   T pp inp a ->
+   T pp inp b
+f  $&  Cons core =
+   tagUnique $ fmap (applyCore $ first f) core
+
+
+infixr 3 &|&
+
+(&|&) ::
+   T pp inp a ->
+   T pp inp b ->
+   T pp inp (a,b)
+Cons coreA  &|&  Cons coreB =
+   tagUnique $ liftA2 combineCore coreA coreB
+
+
+instance Functor (Core pp inp) where
+   fmap f (Simple process) = Simple (fmap (first f) process)
+   fmap f (Plugged prep plg process) = Plugged prep plg (fmap (first f) process)
+
+instance Applicative (Core pp inp) where
+   pure a = lift0Core $ pure a
+   f <*> x = fmap (uncurry ($))  $  combineCore f x
+
+lift0Core :: (forall r. CodeGenFunction r out) -> Core pp inp out
+lift0Core f = Simple (CausalPriv.map (\v -> fmap (flip (,) v) f))
+
+
+instance Functor (T pp inp) where
+   fmap f (Cons x) = tagUnique $ fmap (fmap f) x
+
+instance Applicative (T pp inp) where
+   pure a = tagUnique $ pure $ pure a
+   f <*> x = fmap (uncurry ($))  $  f &|& x
+
+
+lift0 :: (forall r. CodeGenFunction r out) -> T pp inp out
+lift0 f = tagUnique $ pure $ lift0Core f
+
+lift1 ::
+   (forall r. a -> CodeGenFunction r out) ->
+   T pp inp a -> T pp inp out
+lift1 f x = CausalPriv.map f $& x
+
+lift2 ::
+   (forall r. a -> b -> CodeGenFunction r out) ->
+   T pp inp a -> T pp inp b -> T pp inp out
+lift2 f x y = CausalPriv.zipWith f $& x&|&y
+
+
+instance
+   (A.PseudoRing b, A.Real b, A.IntegerConstant b) =>
+      Num (T pp a b) where
+   fromInteger n = pure (A.fromInteger' n)
+   (+) = lift2 A.add
+   (-) = lift2 A.sub
+   (*) = lift2 A.mul
+   abs = lift1 A.abs
+   signum = lift1 A.signum
+
+instance
+   (A.Field b, A.Real b, A.RationalConstant b) =>
+      Fractional (T pp a b) where
+   fromRational x = pure (A.fromRational' x)
+   (/) = lift2 A.fdiv
+
+
+instance (A.Additive b) => Additive.C (T pp a b) where
+   zero = pure A.zero
+   (+) = lift2 A.add
+   (-) = lift2 A.sub
+   negate = lift1 A.neg
+
+instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T pp a b) where
+   one = pure A.one
+   fromInteger n = pure (A.fromInteger' n)
+   (*) = lift2 A.mul
+
+instance (A.Field b, A.RationalConstant b) => Field.C (T pp a b) where
+   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
+   (/) = lift2 A.fdiv
+
+instance
+   (A.Transcendental b, A.RationalConstant b) =>
+      Algebraic.C (T pp a b) where
+   sqrt = lift1 A.sqrt
+   root n x = lift2 A.pow x (Field.recip $ Ring.fromInteger n)
+   x^/r = lift2 A.pow x (Field.fromRational' r)
+
+instance
+   (A.Transcendental b, A.RationalConstant b) =>
+      Trans.C (T pp a b) where
+   pi = lift0 A.pi
+   sin = lift1 A.sin
+   cos = lift1 A.cos
+   (**) = lift2 A.pow
+   exp = lift1 A.exp
+   log = lift1 A.log
+
+   asin _ = error "LLVM missing intrinsic: asin"
+   acos _ = error "LLVM missing intrinsic: acos"
+   atan _ = error "LLVM missing intrinsic: atan"
+
+
+
+fromSignal :: Sig.T a -> T pp inp a
+fromSignal sig =
+   tagUnique $ pure $ Simple (CausalClass.feedFst sig)
+
+
+
+type Input pp a = MR.Reader (pp, a)
+
+plug ::
+   (CutG.Read b, PIn.Default b) =>
+   Input pp a b ->
+   T pp a (PIn.Element b)
+plug accessor =
+   tagUnique $ pure $
+   Plugged
+      (curry $ MR.runReader accessor)
+      PIn.deflt
+      id
+
+askParameter :: Input pp a pp
+askParameter = MR.asks fst
+
+
+runPlugOut ::
+   (Marshal.C pl) =>
+   (Exp pl -> T pp a x) -> POut.T x b ->
+   IO (pp -> pl -> PIO.T a b)
+runPlugOut func pout = do
+   let name = "FunctionalPlug.runPlugOut"
+   ref <- newIORef $ error $ name ++ ": uninitialized parameter reference"
+   case func (Exp (liftIO (readIORef ref))) of
+      Cons core ->
+         case MS.evalState core Set.empty of
+            Simple _ -> error $ name ++ ": no substantial input available"
+               -- Simple process ->
+               --    CausalRender.processIOCore pin process pout
+            Plugged prep pin process ->
+               fmap (\f pp pl -> f (return (pl, return ())) <<^ prep pp) $
+               case fst ^<< process <<^ flip (,) Vault.empty of
+                  CausalPriv.Cons next start stop ->
+                     (\paramd ->
+                        CausalRender.processIOParameterized pin paramd pout) $
+                     Parameterized.Cons
+                        (\p global local a state ->
+                           MaybeCont.lift (Parameterized.loadParam ref p) >>
+                           next global local a state)
+                        (\p ->
+                           Parameterized.loadParam ref p >> start)
+                        (\p global ->
+                           Parameterized.loadParam ref p >> stop global)
+
+run ::
+   (Marshal.C pl) =>
+   (POut.Default b) =>
+   (Exp pl -> T pp a (POut.Element b)) ->
+   IO (pp -> pl -> PIO.T a b)
+run f = runPlugOut f POut.deflt
+
+
+{- |
+Cf. 'F.withArgs'.
+-}
+withArgs ::
+   (Marshal.C pl) =>
+   (MakeArguments a, POut.Default b) =>
+   (Arguments (Input pp a) a -> Exp pl -> T pp a (POut.Element b)) ->
+   IO (pp -> pl -> PIO.T a b)
+withArgs f = withArgsPlugOut f POut.deflt
+
+withArgsPlugOut ::
+   (Marshal.C pl) =>
+   (MakeArguments a) =>
+   (Arguments (Input pp a) a -> Exp pl -> T pp a x) ->
+   POut.T x b ->
+   IO (pp -> pl -> PIO.T a b)
+withArgsPlugOut = withArgsPlugOutStart (MR.asks snd)
+
+withArgsPlugOutStart ::
+   (Marshal.C pl) =>
+   (MakeArguments a) =>
+   Input pp a a ->
+   (Arguments (Input pp a) a -> Exp pl -> T pp a x) ->
+   POut.T x b ->
+   IO (pp -> pl -> PIO.T a b)
+withArgsPlugOutStart fid f = runPlugOut (f (makeArgs fid))
+
+
+
+type family Arguments (f :: * -> *) arg
+
+class MakeArguments arg where
+   makeArgs :: Functor f => f arg -> Arguments f arg
+
+
+type instance Arguments f (EventListBT.T i a) = f (EventListBT.T i a)
+instance MakeArguments (EventListBT.T i a) where
+   makeArgs = id
+
+type instance Arguments f (SV.Vector a) = f (SV.Vector a)
+instance MakeArguments (SV.Vector a) where
+   makeArgs = id
+
+type instance Arguments f (Zip.T a b) = (Arguments f a, Arguments f b)
+instance (MakeArguments a, MakeArguments b) =>
+      MakeArguments (Zip.T a b) where
+   makeArgs f = (makeArgs $ fmap Zip.first f, makeArgs $ fmap Zip.second f)
diff --git a/src/Synthesizer/LLVM/Causal/Helix.hs b/src/Synthesizer/LLVM/Causal/Helix.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/Helix.hs
@@ -0,0 +1,622 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE RebindableSyntax #-}
+{- |
+<http://arxiv.org/abs/0911.5171>
+-}
+module Synthesizer.LLVM.Causal.Helix (
+   -- * time and phase control based on the helix model
+   static,
+   staticPacked,
+   dynamic,
+   dynamicLimited,
+
+   -- * useful control curves
+   zigZag,
+   zigZagPacked,
+   zigZagLong,
+   zigZagLongPacked,
+   ) where
+
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Causal.Functional as Func
+import qualified Synthesizer.LLVM.Generator.Source as Source
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Private as SigPriv
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Causal.RingBufferForward as RingBuffer
+import qualified Synthesizer.LLVM.Frame.SerialVector as SerialExp
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as SerialClass
+import qualified Synthesizer.LLVM.Interpolation as Ip
+import Synthesizer.LLVM.Causal.Functional (($&), (&|&))
+import Synthesizer.LLVM.Private (noLocalPtr)
+
+import Synthesizer.Causal.Class (($*), ($<))
+
+import qualified LLVM.DSL.Expression.Vector as ExprVec
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp, (<*), (>=*))
+
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Vector as MultiValueVec
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Memory as Memory
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import Data.Word (Word)
+
+import Control.Arrow (first, (<<<))
+import Control.Category (id)
+import Control.Functor.HT (unzip)
+import Data.Traversable (mapM)
+import Data.Tuple.HT (mapPair, mapFst)
+
+import qualified Algebra.Ring as Ring
+
+import NumericPrelude.Numeric hiding (splitFraction)
+import NumericPrelude.Base hiding (unzip, zip, mapM, id)
+
+import Prelude ()
+
+
+{- |
+Inputs are @(shape, phase)@.
+
+The shape parameter is limited at the beginning and at the end
+such that only available data is used for interpolation.
+Actually, we allow almost one step less than possible,
+since the right boundary of the interval of admissible @shape@ values is open.
+-}
+static ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Storable.C vh, MultiValue.T vh ~ v) =>
+   (Marshal.C a, MultiValue.Field a, MultiValue.RationalConstant a) =>
+   (MultiValue.Fraction a, MultiValue.NativeFloating a ar) =>
+   (MultiValueVec.NativeFloating a ar, MultiValue.T a ~ am) =>
+   (forall r. Ip.T r nodesLeap am v) ->
+   (forall r. Ip.T r nodesStep am v) ->
+   Exp Int ->
+   Exp a ->
+   Exp (Source.StorableVector vh) ->
+   Causal.T (am, am) v
+static ipLeap ipStep periodInt period vec =
+   let periodWord = wordFromInt periodInt
+       cellMargin = combineMarginParams ipLeap ipStep periodInt
+   in  interpolateCell ipLeap ipStep
+       <<<
+       first (peekCell cellMargin periodWord vec)
+       <<<
+       flattenShapePhaseProc periodWord period
+       <<<
+       first
+          (limitShape cellMargin periodInt
+              (intFromWord $ Source.storableVectorLength vec))
+
+intFromWord :: Exp Word -> Exp Int
+intFromWord = Expr.liftReprM LLVM.bitcast
+
+wordFromInt :: Exp Int -> Exp Word
+wordFromInt = Expr.liftReprM LLVM.bitcast
+
+staticPacked ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Storable.C vh, MultiValue.T vh ~ ve, SerialClass.Element v ~ ve) =>
+   (SerialClass.Size (nodesLeap (nodesStep v)) ~ n,
+    SerialClass.Write (nodesLeap (nodesStep v)),
+    SerialClass.Element (nodesLeap (nodesStep v)) ~
+       nodesLeap (nodesStep (SerialClass.Element v))) =>
+   (TypeNum.Positive n) =>
+   (Marshal.C a, MultiVector.Field a, MultiVector.Real a,
+    MultiVector.Fraction a, MultiVector.RationalConstant a,
+    MultiVector.NativeFloating n a ar) =>
+   (forall r. Ip.T r nodesLeap (Serial.Value n a) v) ->
+   (forall r. Ip.T r nodesStep (Serial.Value n a) v) ->
+   Exp Int ->
+   Exp a ->
+   Exp (Source.StorableVector vh) ->
+   Causal.T (Serial.Value n a, Serial.Value n a) v
+staticPacked ipLeap ipStep periodInt period vec =
+   let periodWord = wordFromInt periodInt
+       cellMargin = combineMarginParams ipLeap ipStep periodInt
+   in  interpolateCell ipLeap ipStep
+       <<<
+       first (CausalPS.pack
+          (peekCell (elementMargin cellMargin) periodWord vec))
+       <<<
+       flattenShapePhaseProcPacked periodWord period
+       <<<
+       first
+          (limitShapePacked cellMargin periodInt
+              (intFromWord $ Source.storableVectorLength vec))
+
+
+{- |
+In contrast to 'dynamic' this one ends
+when the end of the manipulated signal is reached.
+-}
+dynamicLimited ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Marshal.C a, MultiValue.Field a, MultiValue.Fraction a,
+    MultiValue.Select a, MultiValue.Comparison a,
+    MultiValue.NativeFloating a ar,
+    MultiValue.RationalConstant a,
+    MultiValueVec.NativeFloating a ar) =>
+   (MultiValue.T a ~ am) =>
+   (Memory.C v) =>
+   (forall r. Ip.T r nodesLeap am v) ->
+   (forall r. Ip.T r nodesStep am v) ->
+   Exp Int ->
+   Exp a ->
+   Sig.T v ->
+   Causal.T (am, am) v
+dynamicLimited ipLeap ipStep periodInt period sig =
+   dynamicGen
+      (\cellMargin (skips, fracs) ->
+         let windows =
+               (RingBuffer.trackSkip
+                     (wordFromInt $ Ip.marginNumberExp cellMargin) sig)
+                  $& skips
+         in  (windows,
+              Causal.delay1 zero $& skips,
+              Causal.delay1 zero $& fracs))
+      ipLeap ipStep periodInt period
+
+{- |
+If the time control exceeds the end of the input signal,
+then the last waveform is locked.
+This is analogous to 'static'.
+-}
+dynamic ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Marshal.C a, MultiValue.Field a, MultiValue.Fraction a,
+    MultiValue.Select a, MultiValue.Comparison a,
+    MultiValue.NativeFloating a ar,
+    MultiValue.RationalConstant a,
+    MultiValueVec.NativeFloating a ar) =>
+   (MultiValue.T a ~ am) =>
+   (Memory.C v) =>
+   (forall r. Ip.T r nodesLeap am v) ->
+   (forall r. Ip.T r nodesStep am v) ->
+   Exp Int ->
+   Exp a ->
+   Sig.T v ->
+   Causal.T (am, am) v
+dynamic ipLeap ipStep periodInt period sig =
+   dynamicGen
+      (\cellMargin (skips, fracs) ->
+         let {-
+             For conformance with 'static'
+             we stop one step before the definite end.
+             We achieve this by using a buffer
+             that is one step longer than necessary.
+             -}
+             ((running, actualSkips), windows) =
+                mapFst unzip $ unzip $
+                (RingBuffer.trackSkipHold
+                   (wordFromInt (Ip.marginNumberExp cellMargin) + 1) sig)
+                   $& skips
+             holdFracs =
+                Causal.zipWith (\r fr -> Expr.select r fr 1)
+                $&
+                running &|& (Causal.delay1 zero $& fracs)
+         in  (windows, actualSkips, holdFracs))
+      ipLeap ipStep periodInt period
+
+dynamicGen ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Marshal.C a, MultiValue.Field a, MultiValue.Fraction a,
+    MultiValue.Select a, MultiValue.Comparison a,
+    MultiValue.NativeFloating a ar,
+    MultiValue.RationalConstant a,
+    MultiValueVec.NativeFloating a ar) =>
+   (MultiValue.T a ~ am) =>
+   (Memory.C v) =>
+   (Exp (Ip.Margin (nodesLeap (nodesStep v))) ->
+    (Func.T (am, am) (MultiValue.T Word),
+     Func.T (am, am) am) ->
+    (Func.T (am, am) (RingBuffer.T v),
+     Func.T (am, am) (MultiValue.T Word),
+     Func.T (am, am) am)) ->
+   (forall r. Ip.T r nodesLeap am v) ->
+   (forall r. Ip.T r nodesStep am v) ->
+   Exp Int ->
+   Exp a ->
+   Causal.T (am, am) v
+dynamicGen limitMaxShape ipLeap ipStep periodInt period =
+   let periodWord = wordFromInt periodInt
+       cellMargin = combineMarginParams ipLeap ipStep periodInt
+       minShape = wordFromInt $ fst $ shapeMargin cellMargin periodInt
+
+   in  Func.withArgs $ \(shape, phase) ->
+          let (windows, skips, fracs) =
+                 limitMaxShape cellMargin $
+                 unzip (integrateFrac $& (limitMinShape minShape $& shape))
+              (offsets, shapePhases) =
+                 unzip
+                    (flattenShapePhaseProc periodWord period $&
+                       (constantFromWord minShape + fracs)
+                       &|&
+                       (Causal.osciCoreSync $&
+                          phase
+                          &|&
+                          negate
+                             (Causal.map ((/period)) $&
+                                (Causal.map Expr.fromIntegral $& skips))))
+          in interpolateCell ipLeap ipStep $&
+                 (CausalPriv.map
+                    (\(buffer, offset) -> do
+                       p <- Expr.unExp periodWord
+                       cellFromBuffer p buffer offset)
+                  $&
+                  windows
+                  &|&
+                  offsets)
+                 &|&
+                 shapePhases
+
+constantFromWord ::
+   (MultiValue.NativeFloating a ar) =>
+   Exp Word -> Func.T inp (MultiValue.T a)
+constantFromWord x =
+   Func.fromSignal (Causal.map Expr.fromIntegral $* Sig.constant x)
+
+limitMinShape ::
+   (Marshal.C a, MultiValue.Select a, MultiValue.Comparison a,
+    MultiValue.NativeFloating a ar) =>
+   Exp Word ->
+   Causal.T (MultiValue.T a) (MultiValue.T a)
+limitMinShape xLim =
+   Causal.mapAccum
+      (\x lim ->
+         Expr.unzip $
+         Expr.select (x>=*lim) (Expr.zip (x-lim) zero) (Expr.zip zero (lim-x)))
+      (Expr.fromIntegral xLim)
+
+integrateFrac ::
+   (Marshal.C a, MultiValue.Additive a,
+    MultiValueVec.NativeFloating a ar, LLVM.IsPrimitive ar) =>
+   Causal.T (MultiValue.T a) (MultiValue.T Word, MultiValue.T a)
+integrateFrac =
+   Causal.mapAccum
+      (\a frac ->
+         let s = ExprVec.splitFractionToInt (a+frac)
+         in (s, snd s))
+      zero
+
+
+interpolateCell ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (forall r. Ip.T r nodesLeap a v) ->
+   (forall r. Ip.T r nodesStep a v) ->
+   Causal.T (nodesLeap (nodesStep v), (a, a)) v
+interpolateCell ipLeap ipStep =
+   CausalPriv.map
+      (\(nodes, (leap,step)) ->
+         ipLeap leap =<< mapM (ipStep step) nodes)
+
+cellFromBuffer ::
+   (Memory.C a, Ip.C nodesLeap, Ip.C nodesStep) =>
+   MultiValue.T Word ->
+   RingBuffer.T a ->
+   MultiValue.T Word ->
+   LLVM.CodeGenFunction r (nodesLeap (nodesStep a))
+cellFromBuffer periodInt buffer offset =
+   Ip.indexNodesExp
+      (Ip.indexNodesExp (flip RingBuffer.index buffer) A.one)
+      periodInt offset
+
+elementMargin ::
+   Exp (Ip.Margin (nodesLeap (nodesStep v))) ->
+   Exp (Ip.Margin (nodesLeap (nodesStep (SerialClass.Element v))))
+elementMargin = Expr.liftReprM return
+
+peekCell ::
+   (Storable.C a, MultiValue.T a ~ value, Ip.C nodesLeap, Ip.C nodesStep) =>
+   Exp (Ip.Margin (nodesLeap (nodesStep value))) ->
+   Exp Word ->
+   Exp (Source.StorableVector a) ->
+   Causal.T (MultiValue.T Word) (nodesLeap (nodesStep value))
+peekCell margin periodWord vec =
+   CausalPriv.map
+      (\n -> do
+         ~(MultiValue.Cons (ptr,_l)) <- Expr.unExp vec
+         ~(MultiValue.Cons offset) <-
+            Expr.unExp $ intFromWord (Expr.lift0 n) - Ip.marginOffsetExp margin
+         perInt <- Expr.unExp $ intFromWord periodWord
+         Ip.loadNodesExp (Ip.loadNodesExp Storable.load A.one) perInt
+            =<< Storable.advancePtr offset ptr)
+
+
+flattenShapePhaseProc ::
+   (MultiValue.Field a, MultiValue.RationalConstant a, MultiValue.Fraction a) =>
+   (MultiValue.NativeFloating a ar, MultiValueVec.NativeFloating a ar) =>
+   Exp Word ->
+   Exp a ->
+   Causal.T
+      (MultiValue.T a, MultiValue.T a)
+      (MultiValue.T Word, (MultiValue.T a, MultiValue.T a))
+flattenShapePhaseProc periodInt period =
+   Causal.map
+      (\(shape, phase) -> flattenShapePhase periodInt period shape phase)
+
+_flattenShapePhaseProc ::
+   (MultiValue.Field a, MultiValue.RationalConstant a, MultiValue.Fraction a) =>
+   (MultiValue.NativeFloating a ar) =>
+   Exp Word ->
+   Exp a ->
+   Causal.T
+      (MultiValue.T a, MultiValue.T a)
+      (MultiValue.T Word, (MultiValue.T a, MultiValue.T a))
+_flattenShapePhaseProc period32 period =
+   CausalPriv.map
+      (\(shape, phase) -> do
+         perInt <- Expr.unExp period32
+         per <- Expr.unExp period
+         _flattenShapePhase perInt per shape phase)
+
+flattenShapePhaseProcPacked ::
+   (TypeNum.Positive n, MultiVector.Field a, MultiVector.RationalConstant a) =>
+   (MultiVector.Fraction a, MultiVector.NativeFloating n a ar) =>
+   Exp Word ->
+   Exp a ->
+   Causal.T
+      (Serial.Value n a, Serial.Value n a)
+      (Serial.Value n Word, (Serial.Value n a, Serial.Value n a))
+flattenShapePhaseProcPacked periodInt period =
+   Causal.zipWith
+      (flattenShapePhase
+         (SerialExp.upsample periodInt) (SerialExp.upsample period))
+
+flattenShapePhase ::
+   (MultiValue.Field a, MultiValue.RationalConstant a, MultiValue.Fraction a) =>
+   (MultiValueVec.NativeFloating a ar, MultiValueVec.NativeInteger i ir) =>
+   (LLVM.ShapeOf ir ~ LLVM.ShapeOf ar) =>
+   Exp i -> Exp a ->
+   Exp a -> Exp a ->
+   (Exp i, (Exp a, Exp a))
+flattenShapePhase periodInt period shape phase =
+   let qLeap = Expr.fraction $ shape/period - phase
+       (n,qStep) =
+          ExprVec.splitFractionToInt $
+          {-
+          If 'shape' is correctly limited,
+          the value is always non-negative algebraically,
+          but maybe not numerically.
+          -}
+          Expr.max zero $
+          shape - qLeap * ExprVec.fromIntegral periodInt
+   in (n,(qLeap,qStep))
+
+_flattenShapePhase ::
+   (MultiValue.Field a, MultiValue.RationalConstant a, MultiValue.Fraction a) =>
+   (MultiValue.NativeFloating a ar, MultiValue.NativeInteger i ir) =>
+   MultiValue.T i ->
+   MultiValue.T a ->
+   MultiValue.T a -> MultiValue.T a ->
+   LLVM.CodeGenFunction r (MultiValue.T i, (MultiValue.T a, MultiValue.T a))
+_flattenShapePhase = Expr.unliftM4 $ \periodInt period shape phase ->
+   let qLeap = Expr.fraction $ shape/period - phase
+       (n,qStep) =
+          Expr.splitFractionToInt $
+          {-
+          If 'shape' is correctly limited,
+          the value is always non-negative algebraically,
+          but maybe not numerically.
+          -}
+          Expr.max zero $
+          shape - qLeap * Expr.fromIntegral periodInt
+   in  (n,(qLeap,qStep))
+
+
+limitShape ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Marshal.C t, MultiValue.Real t, MultiValue.NativeFloating t tr) =>
+   (i ~ Int) =>
+   Exp (Ip.Margin (nodesLeap (nodesStep value))) ->
+   Exp i -> Exp i -> Causal.MV t t
+limitShape margin periodInt len =
+   Causal.zipWith Expr.limit
+   $<
+   limitShapeSignal margin periodInt len
+
+limitShapePacked ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Marshal.C t, MultiValue.NativeFloating t tr) =>
+   (TypeNum.Positive n, MultiVector.Real t) =>
+   (i ~ Int) =>
+   Exp (Ip.Margin (nodesLeap (nodesStep value))) ->
+   Exp i ->
+   Exp i ->
+   Causal.T (Serial.Value n t) (Serial.Value n t)
+limitShapePacked margin periodInt len =
+   Causal.zipWith
+      (\(minShape,maxShape) shape ->
+         SerialExp.limit
+            (SerialExp.upsample minShape,
+             SerialExp.upsample maxShape)
+            shape)
+   $<
+   limitShapeSignal margin periodInt len
+
+limitShapeSignal ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (Marshal.C t, MultiValue.NativeFloating t tr) =>
+   (i ~ Int) =>
+   Exp (Ip.Margin (nodesLeap (nodesStep value))) ->
+   Exp i ->
+   Exp i ->
+   Sig.T (MultiValue.T t, MultiValue.T t)
+limitShapeSignal margin periodInt len =
+   SigPriv.Cons
+      (\minMax -> noLocalPtr $ \() -> return (minMax, ()))
+      (do
+         limits <-
+            Expr.bundle
+               (mapPair (Expr.fromIntegral, Expr.fromIntegral) $
+                shapeLimits margin periodInt len)
+         return (limits, ()))
+      (const $ return ())
+
+
+shapeLimits ::
+   (Ip.C nodesLeap, Ip.C nodesStep, Exp Int ~ t) =>
+   Exp (Ip.Margin (nodesLeap (nodesStep value))) ->
+   t -> t -> (t, t)
+shapeLimits margin periodInt len =
+   case shapeMargin margin periodInt of
+      (leftMargin, rightMargin) -> (leftMargin, len - rightMargin)
+
+shapeMargin ::
+   (Ip.C nodesLeap, Ip.C nodesStep, Exp Int ~ i) =>
+   Exp (Ip.Margin (nodesLeap (nodesStep value))) ->
+   i -> (i, i)
+shapeMargin margin periodInt =
+   let (marginNumber, marginOffset) =
+         Expr.unzip $
+         Expr.lift1 (uncurry MultiValue.zip . Ip.unzipMargin) margin
+       leftMargin = marginOffset + periodInt
+       rightMargin = marginNumber - leftMargin
+   in  (leftMargin, rightMargin)
+
+_shapeLimits ::
+   (Ip.C nodesLeap, Ip.C nodesStep) =>
+   (MultiValue.NativeFloating t tr) =>
+   (MultiValue.Additive t) =>
+   Ip.Margin (nodesLeap (nodesStep value)) ->
+   Exp Word -> Exp t -> (Exp t, Exp t)
+_shapeLimits margin periodInt len =
+   let (leftMargin, rightMargin) = _shapeMargin margin periodInt
+   in  (Expr.fromIntegral leftMargin, len - Expr.fromIntegral rightMargin)
+
+_shapeMargin ::
+   (Ip.C nodesLeap, Ip.C nodesStep, Ring.C i) =>
+   Ip.Margin (nodesLeap (nodesStep value)) ->
+   i -> (i, i)
+_shapeMargin margin periodInt =
+   let leftMargin = fromIntegral (Ip.marginOffset margin) + periodInt
+       rightMargin = fromIntegral (Ip.marginNumber margin) - leftMargin
+   in  (leftMargin, rightMargin)
+
+combineMarginParams ::
+   (Ip.C nodesStep, Ip.C nodesLeap) =>
+   (forall r. Ip.T r nodesLeap a v) ->
+   (forall r. Ip.T r nodesStep a v) ->
+   Exp Int ->
+   Exp (Ip.Margin (nodesLeap (nodesStep v)))
+combineMarginParams ipLeap ipStep periodInt =
+   let marginLeap = Ip.toMargin ipLeap in
+   let marginStep = Ip.toMargin ipStep in
+   Expr.lift2 Ip.zipMargin
+      (fromIntegral (Ip.marginNumber marginStep) +
+       fromIntegral (Ip.marginNumber marginLeap) * periodInt)
+      (fromIntegral (Ip.marginOffset marginStep) +
+       fromIntegral (Ip.marginOffset marginLeap) * periodInt)
+
+_combineMargins ::
+   Ip.Margin (nodesLeap value) ->
+   Ip.Margin (nodesStep value) ->
+   Int ->
+   Ip.Margin (nodesLeap (nodesStep value))
+_combineMargins marginLeap marginStep periodInt =
+   Ip.Margin {
+      Ip.marginNumber =
+         Ip.marginNumber marginStep +
+         Ip.marginNumber marginLeap * periodInt,
+      Ip.marginOffset =
+         Ip.marginOffset marginStep +
+         Ip.marginOffset marginLeap * periodInt
+   }
+
+
+{- |
+@zigZagLong loopStart loopLength@
+creates a curve that starts at 0
+and is linear until it reaches @loopStart+loopLength@.
+Then it begins looping in a ping-pong manner
+between @loopStart+loopLength@ and @loopStart@.
+It is useful as @shape@ control for looping a sound.
+Input of the causal process is the slope (or frequency) control.
+Slope values must not be negative.
+
+*Main> Sig.renderChunky SVL.defaultChunkSize (Causal.take 25 <<< Helix.zigZagLong 6 10 $* 2) () :: SVL.Vector Float
+VectorLazy.fromChunks [Vector.pack [0.0,1.999999,3.9999995,6.0,8.0,10.0,12.0,14.0,15.999999,14.000001,12.0,10.0,7.999999,6.0,8.0,10.0,12.0,14.0,16.0,14.0,11.999999,9.999998,7.999998,6.0000024,8.000002]]
+-}
+zigZagLong ::
+   (Marshal.C a) =>
+   (MultiValue.Select a, MultiValue.Comparison a, MultiValue.Fraction a) =>
+   (MultiValue.Field a, MultiValue.RationalConstant a) =>
+   Exp a -> Exp a -> Causal.MV a a
+zigZagLong =
+   zigZagLongGen (Causal.fromSignal . Sig.constant) zigZag
+
+zigZagLongPacked ::
+   (Marshal.Vector n a) =>
+   (MultiVector.Field a, MultiVector.Fraction a) =>
+   (MultiVector.RationalConstant a) =>
+   (MultiVector.Select a, MultiVector.Comparison a) =>
+   Exp a -> Exp a -> Causal.T (Serial.Value n a) (Serial.Value n a)
+zigZagLongPacked =
+   zigZagLongGen (Causal.fromSignal . SigPS.constant) zigZagPacked
+
+zigZagLongGen ::
+   (MultiValue.RationalConstant a, MultiValue.Field a) =>
+   (A.RationalConstant al, A.Field al) =>
+   (Exp a -> Causal.T al al) ->
+   (Exp a -> Causal.T al al) ->
+   Exp a -> Exp a -> Causal.T al al
+zigZagLongGen constant zz prefix loop =
+   zz (negate $ prefix/loop) * constant loop + constant prefix
+   <<<
+   id / constant loop
+
+{- |
+@zigZag start@ creates a zig-zag curve with values between 0 and 1, inclusively,
+that is useful as @shape@ control for looping a sound.
+Input of the causal process is the slope (or frequency) control.
+Slope values must not be negative.
+The start value must be at most 2 and may be negative.
+-}
+zigZag ::
+   (Marshal.C a) =>
+   (MultiValue.Select a, MultiValue.Comparison a, MultiValue.Fraction a) =>
+   (MultiValue.Field a, MultiValue.RationalConstant a) =>
+   Exp a -> Causal.MV a a
+zigZag start =
+   Causal.map (\x -> 1 - abs (1-x))
+   <<<
+   Causal.mapAccum
+      (\d t0 -> let t1 = t0+d in (t0, wrap Expr.select (0<*) t1))
+      start
+
+zigZagPacked ::
+   (TypeNum.Positive n) =>
+   (Marshal.C a) =>
+   (MultiVector.Field a, MultiVector.Fraction a) =>
+   (MultiVector.RationalConstant a) =>
+   (MultiVector.Select a, MultiVector.Comparison a) =>
+   Exp a -> Causal.T (Serial.Value n a) (Serial.Value n a)
+zigZagPacked start =
+   Causal.map (\x -> 1 - abs (1-x))
+   <<<
+   Causal.mapAccum
+      (\d t0 ->
+         let (t1,cum) = SerialExp.cumulate t0 d
+         in (wrap SerialExp.select (SerialExp.cmp LLVM.CmpLT zero) cum, t1))
+      start
+
+wrap ::
+   (MultiValue.Field a, MultiValue.Fraction a, MultiValue.RationalConstant a) =>
+   (Exp b -> Exp a -> Exp a -> Exp a) ->
+   (Exp a -> Exp b) ->
+   Exp a -> Exp a
+wrap select positive a = select (positive a) (2 * Expr.fraction (a/2)) a
diff --git a/src/Synthesizer/LLVM/Causal/Parameterized.hs b/src/Synthesizer/LLVM/Causal/Parameterized.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/Parameterized.hs
@@ -0,0 +1,67 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Causal.Parameterized where
+
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+
+import LLVM.DSL.Expression (Exp(Exp))
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+
+import Control.Monad.IO.Class (liftIO)
+
+import Data.IORef (IORef, newIORef, readIORef, writeIORef)
+
+
+data T p a b =
+   forall global local state.
+      (Memory.C global, LLVM.IsSized local, Memory.C state) =>
+      Cons (forall r c.
+            (Tuple.Phi c) =>
+            p -> global -> LLVM.Value (LLVM.Ptr local) ->
+            a -> state -> MaybeCont.T r c (b, state))
+           (forall r. p -> LLVM.CodeGenFunction r (global, state))
+           (forall r. p -> global -> LLVM.CodeGenFunction r ())
+
+
+fromProcess :: String -> (Exp p -> Causal.T a b) -> IO (T (MultiValue.T p) a b)
+fromProcess name f = do
+   ref <- newIORef $ error $ name ++ ": uninitialized parameter reference"
+   return $
+      case f (Exp (liftIO (readIORef ref))) of
+         Causal.Cons next start stop ->
+            Cons
+               (\p global local a state ->
+                  liftIO (writeIORef ref p) >> next global local a state)
+               (\p -> liftIO (writeIORef ref p) >> start)
+               (\p global -> liftIO (writeIORef ref p) >> stop global)
+
+
+fromProcessPtr ::
+   (Marshal.C p) =>
+   String -> (Exp p -> Causal.T a b) ->
+   IO (T (LLVM.Value (LLVM.Ptr (Marshal.Struct p))) a b)
+fromProcessPtr name f = do
+   ref <- newIORef $ error $ name ++ ": uninitialized parameter reference"
+   return $
+      case f (Exp (liftIO (readIORef ref))) of
+         Causal.Cons next start stop ->
+            Cons
+               (\p global local a state ->
+                  MaybeCont.lift (loadParam ref p) >> next global local a state)
+               (\p -> loadParam ref p >> start)
+               (\p global -> loadParam ref p >> stop global)
+
+loadParam ::
+   (Marshal.C param) =>
+   IORef (MultiValue.T param) ->
+   LLVM.Value (LLVM.Ptr (Marshal.Struct param)) ->
+   LLVM.CodeGenFunction r ()
+loadParam ref ptr = liftIO . writeIORef ref =<< Memory.load ptr
diff --git a/src/Synthesizer/LLVM/Causal/Private.hs b/src/Synthesizer/LLVM/Causal/Private.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/Private.hs
@@ -0,0 +1,301 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Causal.Private where
+
+import qualified Synthesizer.LLVM.Generator.Private as Sig
+import Synthesizer.LLVM.Private (getPairPtrs, noLocalPtr, unbool)
+
+import qualified Synthesizer.Causal.Class as CausalClass
+import qualified Synthesizer.Causal.Utility as ArrowUtil
+import Synthesizer.Causal.Class (($>))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Control as C
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+import LLVM.Core (CodeGenFunction)
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Control.Category as Cat
+import Control.Arrow (Arrow, arr, first, (&&&), (<<<))
+import Control.Category (Category)
+import Control.Applicative (Applicative, pure, liftA2, (<*>), (<$>))
+
+import Data.Tuple.Strict (mapFst, zipPair)
+import Data.Word (Word)
+
+import qualified Number.Ratio as Ratio
+import qualified Algebra.Field as Field
+import qualified Algebra.Ring as Ring
+import qualified Algebra.Additive as Additive
+
+import NumericPrelude.Base hiding (map, zip, zipWith, init)
+
+import qualified Prelude as P
+
+
+data T a b =
+   forall global local state.
+      (Memory.C global, LLVM.IsSized local, Memory.C state) =>
+      Cons (forall r c.
+            (Tuple.Phi c) =>
+            global -> LLVM.Value (LLVM.Ptr local) ->
+            a -> state -> MaybeCont.T r c (b, state))
+               -- compute next value
+           (forall r. CodeGenFunction r (global, state))
+               -- initial state
+           (forall r. global -> CodeGenFunction r ())
+               -- cleanup
+
+
+type instance CausalClass.ProcessOf Sig.T = T
+
+instance CausalClass.C T where
+   type SignalOf T = Sig.T
+   toSignal (Cons next start stop) = Sig.Cons
+      (\global local -> next global local ())
+      start
+      stop
+   fromSignal (Sig.Cons next start stop) = Cons
+      (\global local _ -> next global local)
+      start
+      stop
+
+
+noGlobal ::
+   (LLVM.IsSized local, Memory.C state) =>
+   (forall r c.
+    (Tuple.Phi c) =>
+    LLVM.Value (LLVM.Ptr local) -> a -> state -> MaybeCont.T r c (b, state)) ->
+   (forall r. CodeGenFunction r state) ->
+   T a b
+noGlobal next start =
+   Cons (const next) (fmap ((,) ()) start) return
+
+simple ::
+   (Memory.C state) =>
+   (forall r c. (Tuple.Phi c) => a -> state -> MaybeCont.T r c (b, state)) ->
+   (forall r. CodeGenFunction r state) ->
+   T a b
+simple next start = noGlobal (noLocalPtr next) start
+
+mapAccum ::
+   (Memory.C state) =>
+   (forall r. a -> state -> CodeGenFunction r (b, state)) ->
+   (forall r. CodeGenFunction r state) ->
+   T a b
+mapAccum next =
+   simple (\a s -> MaybeCont.lift $ next a s)
+
+map ::
+   (forall r. a -> CodeGenFunction r b) ->
+   T a b
+map f =
+   mapAccum (\a s -> fmap (flip (,) s) $ f a) (return ())
+
+zipWith ::
+   (forall r. a -> b -> CodeGenFunction r c) ->
+   T (a,b) c
+zipWith f = map (uncurry f)
+
+
+instance Category T where
+   id = map return
+   Cons nextB startB stopB . Cons nextA startA stopA = Cons
+      (\(globalA, globalB) local a (sa0,sb0) -> do
+         (localA,localB) <- getPairPtrs local
+         (b,sa1) <- nextA globalA localA a sa0
+         (c,sb1) <- nextB globalB localB b sb0
+         return (c, (sa1,sb1)))
+      (liftA2 zipPair startA startB)
+      (\(globalA, globalB) -> stopA globalA >> stopB globalB)
+
+instance Arrow T where
+   arr f = map (return . f)
+   first (Cons next start stop) = Cons (firstNext next) start stop
+
+firstNext ::
+   (Functor m) =>
+   (global -> local -> a -> s -> m (b, s)) ->
+   global -> local ->  (a, c) -> s -> m ((b, c), s)
+firstNext next global local (b,d) s0 =
+   fmap
+      (\(c,s1) -> ((c,d), s1))
+      (next global local b s0)
+
+
+instance Functor (T a) where
+   fmap = flip (>>^)
+
+instance Applicative (T a) where
+   pure = ArrowUtil.pure
+   (<*>) = ArrowUtil.apply
+
+
+infixr 1 >>^, ^>>
+
+(>>^) :: T a b -> (b -> c) -> T a c
+Cons next start stop >>^ f =
+   Cons
+      (\global local a state -> mapFst f <$> next global local a state)
+      start stop
+
+(^>>) :: (a -> b) -> T b c -> T a c
+f ^>> Cons next start stop =
+   Cons
+      (\global local -> next global local . f)
+      start stop
+
+
+mapProc ::
+   (forall r. b -> CodeGenFunction r c) ->
+   T a b -> T a c
+mapProc f x = map f <<< x
+
+zipProcWith ::
+   (forall r. b -> c -> CodeGenFunction r d) ->
+   T a b -> T a c -> T a d
+zipProcWith f x y = zipWith f <<< x&&&y
+
+
+instance (A.Additive b) => Additive.C (T a b) where
+   zero = pure A.zero
+   negate = mapProc A.neg
+   (+) = zipProcWith A.add
+   (-) = zipProcWith A.sub
+
+instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T a b) where
+   one = pure A.one
+   fromInteger n = pure (A.fromInteger' n)
+   (*) = zipProcWith A.mul
+
+instance (A.Field b, A.RationalConstant b) => Field.C (T a b) where
+   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
+   (/) = zipProcWith A.fdiv
+
+
+instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => P.Num (T a b) where
+   fromInteger n = pure (A.fromInteger' n)
+   negate = mapProc A.neg
+   (+) = zipProcWith A.add
+   (-) = zipProcWith A.sub
+   (*) = zipProcWith A.mul
+   abs = mapProc A.abs
+   signum = mapProc A.signum
+
+instance
+      (A.Field b, A.Real b, A.RationalConstant b) => P.Fractional (T a b) where
+   fromRational x = pure (A.fromRational' x)
+   (/) = zipProcWith A.fdiv
+
+
+{- |
+Not quite the loop of ArrowLoop
+because we need a delay of one time step
+and thus an initialization value.
+
+For a real ArrowLoop.loop, that is a zero-delay loop,
+we would formally need a MonadFix instance of CodeGenFunction.
+But this will not become reality, since LLVM is not able to re-order code
+in a way that allows to access a result before creating the input.
+-}
+loop ::
+   (Memory.C c) =>
+   (forall r. CodeGenFunction r c) -> T (a,c) (b,c) -> T a b
+loop initial (Cons next start stop) = Cons
+   (\global local a0 (c0,s0) -> do
+      ((b1,c1), s1) <- next global local (a0,c0) s0
+      return (b1,(c1,s1)))
+   (liftA2 (\ini (global,s) -> (global,(ini,s))) initial start)
+   stop
+
+
+replicateSerial ::
+   (Tuple.Undefined a, Tuple.Phi a) =>
+   Exp Word -> T a a -> T a a
+replicateSerial n proc =
+   (\a -> ((),a)) ^>> replicateControlled n (snd^>>proc)
+
+replicateControlled ::
+   (Tuple.Undefined a, Tuple.Phi a) =>
+   Exp Word -> T (c,a) a -> T (c,a) a
+replicateControlled n (Cons next start stop) = Cons
+   (\(len,globalStates) local (c,a) () ->
+      MaybeCont.fromMaybe $ fmap (\(_,ms) -> flip (,) () <$> ms) $
+         MaybeCont.arrayLoop len globalStates a $
+               \globalStatePtr a0 -> do
+            (global, s0) <- MaybeCont.lift $ Memory.load globalStatePtr
+            (a1,s1) <- next global local (c,a0) s0
+            MaybeCont.lift $
+               Memory.store s1 =<<
+               LLVM.getElementPtr0 globalStatePtr (TypeNum.d1, ())
+            return a1)
+   (do
+      MultiValue.Cons len <- Expr.unExp n
+      globalStates <- LLVM.arrayMalloc len
+      C.arrayLoop len globalStates () $ \globalStatePtr () ->
+         flip Memory.store globalStatePtr =<< start
+      return ((len,globalStates), ()))
+   (\(len,globalStates) -> do
+      C.arrayLoop len globalStates () $ \globalStatePtr () ->
+         stop =<< Memory.load
+            =<< LLVM.getElementPtr0 globalStatePtr (TypeNum.d0, ())
+      LLVM.free globalStates)
+
+{-
+We can implement 'replicateControlled' in terms of 'replicateSerial'
+but this adds constraints @(Tuple.Undefined c, Tuple.Phi c)@.
+-}
+replicateControlledAlt ::
+   (Tuple.Undefined a, Tuple.Phi a) =>
+   (Tuple.Undefined c, Tuple.Phi c) =>
+   Exp Word -> T (c,a) a -> T (c,a) a
+replicateControlledAlt n proc =
+   replicateSerial n (arr fst &&& proc) >>^ snd
+
+replicateParallel ::
+   (Tuple.Undefined b, Tuple.Phi b) =>
+   Exp Word -> Sig.T b -> T (b,b) b -> T a b -> T a b
+replicateParallel n z cum p =
+   replicateControlled n (cum <<< first p) $> z
+
+
+quantizeLift ::
+   (Memory.C b, Marshal.C c, MultiValue.IntegerConstant c,
+    MultiValue.Additive c, MultiValue.Comparison c) =>
+   T a b -> T (MultiValue.T c, a) b
+quantizeLift (Cons next start stop) = Cons
+   (\global local (k, a0) yState0 -> do
+      (yState1, frac1) <-
+         MaybeCont.fromBool $
+         C.whileLoop
+            (LLVM.valueOf True, yState0)
+            (\(cont1, (_, frac0)) ->
+               LLVM.and cont1 . unbool
+                  =<< MultiValue.cmp LLVM.CmpLE frac0 A.zero)
+            (\(_,((_,state01), frac0)) ->
+               MaybeCont.toBool $ liftA2 (,)
+                  (next global local a0 state01)
+                  (MaybeCont.lift $ A.add frac0 k))
+
+      frac2 <- MaybeCont.lift $ A.sub frac1 A.one
+      return (fst yState1, (yState1, frac2)))
+{- using this initialization code we would not need undefined values
+   (do (global,s) <- start
+       (a,_) <- next s
+       return (global, ((a,s), A.zero))
+-}
+   (do
+      (global,s) <- start
+      return (global, ((Tuple.undef, s), A.zero)))
+   stop
diff --git a/src/Synthesizer/LLVM/Causal/Process.hs b/src/Synthesizer/LLVM/Causal/Process.hs
--- a/src/Synthesizer/LLVM/Causal/Process.hs
+++ b/src/Synthesizer/LLVM/Causal/Process.hs
@@ -1,756 +1,787 @@
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-module Synthesizer.LLVM.Causal.Process (
-   C(simple, replicateControlled),
-   T,
-   amplify,
-   amplifyStereo,
-   apply,
-   applyFst,
-   applySnd,
-   applyConst,
-   applyConstFst,
-   applyConstSnd,
-   (CausalClass.$<), (CausalClass.$>), (CausalClass.$*),
-   ($<#), ($>#), ($*#),
-   feedFst,
-   feedSnd,
-   feedConstFst,
-   feedConstSnd,
-   first,
-   envelope,
-   envelopeStereo,
-   fromModifier,
-   fromSignal,
-   toSignal,
-   loopConst,
-   loopZero,
-   delay1Zero,
-   feedbackControlledZero,
-   map,
-   mapAccum,
-   zipWith,
-   mapProc,
-   zipProcWith,
-   mix,
-   takeWhile,
-   pipeline,
-   stereoFromVector,
-   vectorize,
-   replaceChannel,
-   arrayElement,
-   element,
-   osciCoreSync,
-   osciCore,
-   osci,
-   shapeModOsci,
-   skip,
-   foldChunks,
-   foldChunksPartial,
-   frequencyModulation,
-   interpolateConstant,
-   quantizeLift,
-   applyStorable,
-   applyStorableChunky,
-   runStorableChunky,
-   ) where
-
-import Synthesizer.LLVM.Causal.ProcessPrivate
-
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as Sig
-import qualified Synthesizer.LLVM.Simple.Value as Value
-import qualified Synthesizer.LLVM.Fold as Fold
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Frame as Frame
-import qualified Synthesizer.LLVM.ForeignPtr as ForeignPtr
-
-import qualified Synthesizer.Plain.Modifier as Modifier
-import qualified Synthesizer.Causal.Class as CausalClass
-
-import qualified Data.StorableVector.Lazy as SVL
-import qualified Data.StorableVector as SV
-import qualified Data.StorableVector.Base as SVB
-
-import qualified LLVM.DSL.Execution as Exec
-
-import qualified LLVM.Extra.Multi.Vector as MultiVector
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import qualified LLVM.Extra.Control as C
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-          (CodeGenFunction, ret, Value, valueOf,
-           IsConst, IsFirstClass, IsArithmetic, IsPrimitive)
-
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Base.Proxy (Proxy)
-import Type.Data.Num.Decimal (D2, (:<:))
-
-import qualified Control.Arrow    as Arr
-import Control.Monad.Trans.State (runState)
-import Control.Arrow (arr, (<<<), (>>>), (&&&))
-import Control.Monad (liftM2)
-import Control.Applicative (liftA3, (<$>))
-
-import qualified Data.List as List
-import Data.Tuple.HT (swap)
-import Data.Word (Word)
-
-import Foreign.Ptr (Ptr)
-import Control.Exception (bracket)
-import qualified System.Unsafe as Unsafe
-
-import Prelude hiding (and, map, zip, zipWith, init, takeWhile)
-
-
-
-fromModifier ::
-   (C process) =>
-   (Value.Flatten ah, Value.Registers ah ~ al,
-    Value.Flatten bh, Value.Registers bh ~ bl,
-    Value.Flatten ch, Value.Registers ch ~ cl,
-    Value.Flatten sh, Value.Registers sh ~ sl,
-    Memory.C sl) =>
-   Modifier.Simple sh ch ah bh -> process (cl,al) bl
-fromModifier (Modifier.Simple initial step) =
-   mapAccum
-      (\(c,a) s ->
-         Value.flatten $
-         runState
-            (step (Value.unfold c) (Value.unfold a))
-            (Value.unfold s))
-      (Value.flatten initial)
-
-
-apply :: T a b -> Sig.T a -> Sig.T b
-apply = CausalClass.apply
-
-feedFst :: Sig.T a -> T b (a,b)
-feedFst = CausalClass.feedFst
-
-feedSnd :: Sig.T a -> T b (b,a)
-feedSnd = CausalClass.feedSnd
-
-feedConstFst :: (Tuple.Value a, Tuple.ValueOf a ~ al) => a -> T b (al,b)
-feedConstFst = CausalClass.feedConstFst . Tuple.valueOf
-
-feedConstSnd :: (Tuple.Value a, Tuple.ValueOf a ~ al) => a -> T b (b,al)
-feedConstSnd = CausalClass.feedConstSnd . Tuple.valueOf
-
-
-applyFst :: T (a,b) c -> Sig.T a -> T b c
-applyFst = CausalClass.applyFst
-
-applySnd :: T (a,b) c -> Sig.T b -> T a c
-applySnd = CausalClass.applySnd
-
-applyConst ::
-   (Tuple.Value a, Tuple.ValueOf a ~ al) =>
-   T al b -> a -> Sig.T b
-applyConst proc =
-   CausalClass.applyConst proc . Tuple.valueOf
-
-applyConstFst ::
-   (Tuple.Value a, Tuple.ValueOf a ~ al) =>
-   T (al,b) c -> a -> T b c
-applyConstFst proc =
-   CausalClass.applyConstFst proc . Tuple.valueOf
-
-applyConstSnd ::
-   (Tuple.Value b, Tuple.ValueOf b ~ bl) =>
-   T (a,bl) c -> b -> T a c
-applyConstSnd proc =
-   CausalClass.applyConstSnd proc . Tuple.valueOf
-
-
-infixl 0 $<#, $>#, $*#
-
-{- |
-provide constant input in a comfortable way
--}
-($*#) ::
-   (C process, CausalClass.SignalOf process ~ signal,
-    Tuple.Value ah, Tuple.ValueOf ah ~ a) =>
-   process a b -> ah -> signal b
-proc $*# x = CausalClass.applyConst proc $ Tuple.valueOf x
-
-($<#) ::
-   (C process, Tuple.Value ah, Tuple.ValueOf ah ~ a) =>
-   process (a,b) c -> ah -> process b c
-proc $<# x = CausalClass.applyConstFst proc $ Tuple.valueOf x
-
-($>#) ::
-   (C process, Tuple.Value bh, Tuple.ValueOf bh ~ b) =>
-   process (a,b) c -> bh -> process a c
-proc $># x = CausalClass.applyConstSnd proc $ Tuple.valueOf x
-
-
-
-{- |
-You may also use '(+)'.
--}
-mix ::
-   (C process, A.Additive a) =>
-   process (a, a) a
-mix = zipWith Frame.mix
-
-
-{- |
-You may also use '(*)'.
--}
-envelope ::
-   (C process, A.PseudoRing a) =>
-   process (a, a) a
-envelope = zipWith Frame.amplifyMono
-
-envelopeStereo ::
-   (C process, A.PseudoRing a) =>
-   process (a, Stereo.T a) (Stereo.T a)
-envelopeStereo = zipWith Frame.amplifyStereo
-
-amplify ::
-   (C process, IsArithmetic a, IsConst a) =>
-   a -> process (Value a) (Value a)
-amplify x =
-   map (Frame.amplifyMono (valueOf x))
-
-amplifyStereo ::
-   (C process, IsArithmetic a, IsConst a) =>
-   a -> process (Stereo.T (Value a)) (Stereo.T (Value a))
-amplifyStereo x =
-   map (Frame.amplifyStereo (valueOf x))
-
-
-
-loopConst ::
-   (C process, Memory.C c) =>
-   c -> process (a,c) (b,c) -> process a b
-loopConst init =
-   alter
-      (\(Core next start stop) ->
-          Core
-             (loopNext next)
-             (fmap ((,) init) . start)
-             (stop . snd))
-
-{- |
-Like 'Synthesizer.LLVM.CausalParameterized.loop'
-but uses zero as initial value
-and it does not need a zero as Haskell value.
--}
-loopZero ::
-   (C process, A.Additive c, Memory.C c) =>
-   process (a,c) (b,c) -> process a b
-loopZero = loopConst A.zero
-
-delay1Zero ::
-   (C process, A.Additive a, Memory.C a) =>
-   process a a
-delay1Zero = loopZero (arr swap)
-
-
-{- |
-This allows to compute a chain of equal processes efficiently,
-if all of these processes can be bundled in one vectorial process.
-Applications are an allpass cascade or an FM operator cascade.
-
-The function expects that the vectorial input process
-works like parallel scalar processes.
-The different pipeline stages may be controlled by different parameters,
-but the structure of all pipeline stages must be equal.
-Our function feeds the input of the pipelined process
-to the zeroth element of the Vector.
-The result of processing the i-th element (the i-th channel, so to speak)
-is fed to the (i+1)-th element.
-The (n-1)-th element of the vectorial process is emitted
-as output of the pipelined process.
-
-The pipeline necessarily introduces a delay of (n-1) values.
-For simplification we extend this to n values delay.
-If you need to combine the resulting signal from the pipeline
-with another signal in a 'zip'-like way,
-you may delay that signal with @pipeline id@.
-The first input values in later stages of the pipeline
-are initialized with zero.
-If this is not appropriate for your application,
-then we may add a more sensible initialization.
--}
-pipeline ::
-   (C process,
-    TypeNum.Positive n, MultiVector.C x,
-    v ~ MultiVector.T n x,
-    a ~ MultiValue.T x,
-    Tuple.Zero v, Memory.C v) =>
-   process v v -> process a a
-pipeline vectorProcess =
-   loopConst MultiVector.zero $
-      map (uncurry MultiVector.shiftUp)
-      >>>
-      Arr.second vectorProcess
-
-
-feedbackControlledZero ::
-   (C process, A.Additive c, Memory.C c) =>
-   process ((ctrl,a),c) b -> process (ctrl,b) c -> process (ctrl,a) b
-feedbackControlledZero forth back =
-   loopZero (feedbackControlledAux forth back)
-
-
-{-
-In order to let this work we have to give the disable-mmx option somewhere,
-but where?
--}
-stereoFromVector ::
-   (C process, IsPrimitive a, IsPrimitive b) =>
-   process (Value (LLVM.Vector D2 a)) (Value (LLVM.Vector D2 b)) ->
-   process (Stereo.T (Value a)) (Stereo.T (Value b))
-stereoFromVector proc =
-   map Frame.stereoFromVector <<<
-   proc <<<
-   map Frame.vectorFromStereo
-
-
-{-
-insert and extract instructions will be in opposite order,
-no matter whether we use foldr or foldl
-and independent from the order of proc and channel in replaceChannel.
-However, LLVM neglects the order anyway.
--}
-vectorize ::
-   (C process,
-    TypeNum.Positive n,
-    MultiVector.C x, MultiValue.T x ~ a, MultiVector.T n x ~ va,
-    MultiVector.C y, MultiValue.T y ~ b, MultiVector.T n y ~ vb) =>
-   process a b -> process va vb
-vectorize proc =
-   withSize $ \n ->
-      foldl
-         (\acc i -> replaceChannel i proc acc)
-         (arr (const $ Tuple.undef)) $
-      List.take (TypeNum.integralFromSingleton n) [0 ..]
-
-withSize ::
-   (TypeNum.Positive n, MultiVector.T n a ~ v) =>
-   (TypeNum.Singleton n -> f v) ->
-   f v
-withSize f = f TypeNum.singleton
-
-{- |
-Given a vector process, replace the i-th output by output
-that is generated by a scalar process from the i-th input.
--}
-replaceChannel ::
-   (C process,
-    TypeNum.Positive n,
-    MultiVector.C x, MultiValue.T x ~ a, MultiVector.T n x ~ va,
-    MultiVector.C y, MultiValue.T y ~ b, MultiVector.T n y ~ vb) =>
-   Int -> process a b -> process va vb -> process va vb
-replaceChannel i channel proc =
-   let li = valueOf $ fromIntegral i
-   in  zipWith (MultiVector.insert li) <<<
-          (channel <<< map (MultiVector.extract li)) &&&
-          proc
-
-{- |
-Read the i-th element from each array.
--}
-arrayElement ::
-   (C process, IsFirstClass a,
-    TypeNum.Natural index, TypeNum.Natural dim,
-    index :<: dim) =>
-   Proxy index -> process (Value (LLVM.Array dim a)) (Value a)
-arrayElement i =
-   map (\array -> LLVM.extractvalue array i)
-
-{- |
-Read the i-th element from an aggregate type.
--}
-element ::
-   (C process, IsFirstClass a, LLVM.GetValue agg index,
-    LLVM.ValueType agg index ~ a) =>
-   index -> process (Value agg) (Value a)
-element i =
-   map (\array -> LLVM.extractvalue array i)
-
-
-
-{- |
-Compute the phases from phase distortions and frequencies.
-
-It's like integrate but with wrap-around performed by @fraction@.
-For FM synthesis we need also negative phase distortions,
-thus we use 'A.addToPhase' which supports that.
--}
-osciCore, _osciCore, osciCoreSync ::
-   (C process, Memory.C t, A.Fraction t) =>
-   process (t, t) (t)
-_osciCore =
-   zipWith A.addToPhase <<<
-   Arr.second
-      (mapAccum
-         (\a s -> do
-            b <- A.incPhase a s
-            return (s,b))
-         (return A.zero))
-
-{-
-This could be implemented using a generalized frequencyModulation,
-however, osciCoreSync allows for negative phase differences.
--}
-osciCoreSync =
-   zipWith A.addToPhase <<<
-   Arr.second
-      (mapAccum
-         (\a s -> do
-            b <- A.incPhase a s
-            return (b,b))
-         (return A.zero))
-
-osciCore =
-   zipWith A.addToPhase <<<
-   Arr.second (loopZero (arr snd &&& zipWith A.incPhase))
-
-osci ::
-   (C process, Memory.C t, A.Fraction t) =>
-   (forall r. t -> CodeGenFunction r y) ->
-   process (t, t) y
-osci wave =
-   map wave <<< osciCore
-
-shapeModOsci ::
-   (C process, Memory.C t, A.Fraction t) =>
-   (forall r. c -> t -> CodeGenFunction r y) ->
-   process (c, (t, t)) y
-shapeModOsci wave =
-   zipWith wave <<< Arr.second osciCore
-
-
-{- |
-Feeds a signal into a causal process while holding or skipping signal elements
-according to the process input.
-The skip happens after a value is passed from the fed signal.
-
-@skip x $* 0@ repeats the first signal value in the output.
-@skip x $* 1@ feeds the signal to the output as is.
-@skip x $* 2@ feeds the signal to the output with double speed.
--}
-skip ::
-   (C process, CausalClass.SignalOf process ~ signal,
-    Tuple.Undefined a, Tuple.Phi a, Memory.C a) =>
-   signal a -> process (Value Word) a
-skip =
-   alterSignal
-      (\(Sig.Core next start stop) -> Core
-         (\context n1 (yState0,n0) -> do
-            yState1@(y,_) <-
-               MaybeCont.fromMaybe $ fmap snd $
-               MaybeCont.fixedLengthLoop n0 yState0 $
-               next context . snd
-            return (y, (yState1,n1)))
-         (fmap (\s -> ((Tuple.undef, s), A.one)) . start)
-         (\((_y,state),_k) -> stop state))
-
-{- |
-The input of the process is a sequence of chunk sizes.
-The signal is chopped into chunks of these sizes
-and each chunk is folded using
-the given initial value and the accumulation function.
-A trailing incomplete chunk will be ignored.
--}
-foldChunks ::
-   (C process, CausalClass.SignalOf process ~ signal, Tuple.Undefined b, Tuple.Phi b) =>
-   Fold.T a b -> signal a -> process (Value Word) b
-foldChunks (Fold.Cons accum initial) =
-   alterSignal
-      (\(Sig.Core next start stop) -> Core
-         (\context n state ->
-            MaybeCont.fromMaybe $ fmap snd $
-            MaybeCont.fixedLengthLoop n (initial,state) $ \(b0,state0) -> do
-               (a,state1) <- next context state0
-               b1 <- MaybeCont.lift $ accum b0 a
-               return (b1,state1))
-         start
-         stop)
-
-{- |
-Like 'foldChunks' but an incomplete chunk at the end
-is treated like a complete one.
--}
-foldChunksPartial ::
-   (C process, CausalClass.SignalOf process ~ signal,
-    Tuple.Undefined a, Tuple.Phi a, Tuple.Undefined b, Tuple.Phi b) =>
-   Fold.T a b -> signal a -> process (Value Word) b
-foldChunksPartial (Fold.Cons accum initial) =
-   alterSignal
-      (\(Sig.Core next start stop) -> Core
-         (\context n runState0 -> do
-            ((i,b), runState1) <-
-               MaybeCont.lift $
-               C.whileLoopShared ((n, initial), runState0) $
-                     \((i0,b0), (run,s0)) ->
-                  (A.and run =<< A.cmp LLVM.CmpGT i0 A.zero,
-                   do mas1 <- MaybeCont.toMaybe $ next context s0
-                      Maybe.run mas1
-                        (return ((i0,b0), (valueOf False, s0)))
-                        (\(a,s1) -> do
-                           b1 <- accum b0 a
-                           i1 <- A.dec i0
-                           return ((i1,b1), (valueOf True, s1))))
-            MaybeCont.guard =<< MaybeCont.lift (A.cmp LLVM.CmpLT i n)
-            return (b, runState1))
-         (fmap ((,) (valueOf True)) . start)
-         (stop . snd))
-
-{-
-It is quite similar to quantizeLift but the control is the reciprocal.
-This is especially a problem since we need the fractional part for interpolation.
--}
-frequencyModulation ::
-   (C process, CausalClass.SignalOf process ~ signal,
-    SoV.IntegerConstant a, LLVM.IsFloating a,
-    LLVM.CmpRet a, LLVM.CmpResult a ~ Bool, LLVM.IsSized a,
-    Tuple.Undefined nodes, Tuple.Phi nodes, Memory.C nodes) =>
-   (forall r. Value a -> nodes -> CodeGenFunction r v) ->
-   signal nodes -> process (Value a) v
-frequencyModulation ip =
-   alterSignal (\(Sig.Core next start stop) -> Core
-      (\context k yState0 -> do
-         ((nodes2,state2), ss2) <-
-            MaybeCont.fromBool $
-            C.whileLoop
-               (valueOf True, yState0)
-               (\(cont0, (_, ss0)) ->
-                  LLVM.and cont0 =<< A.fcmp LLVM.FPOGE ss0 A.one)
-               (\(_,((_,state0), ss0)) ->
-                  MaybeCont.toBool $ liftM2 (,)
-                     (next context state0)
-                     (MaybeCont.lift $ A.sub ss0 A.one))
-
-         MaybeCont.lift $ do
-            y <- ip ss2 nodes2
-            ss3 <- A.add ss2 k
-            return (y, ((nodes2, state2), ss3)))
-      (fmap (\sa -> ((Tuple.undef, sa), A.one)) . start)
-      (\((_y01,state),_ss) -> stop state))
-
-
-{- |
-Stretch signal in time by a time-varying factor.
--}
-interpolateConstant ::
-   (C process, CausalClass.SignalOf process ~ signal,
-    Memory.C a, LLVM.IsSized b, SoV.IntegerConstant b,
-    LLVM.IsFloating b, LLVM.CmpRet b, LLVM.CmpResult b ~ Bool) =>
-   signal a -> process (Value b) a
-interpolateConstant xs =
-   quantizeLift (CausalClass.fromSignal xs) $># ()
-
-
-quantizeLift ::
-   (C process, Memory.C b,
-    SoV.IntegerConstant c, LLVM.IsFloating c,
-    LLVM.CmpRet c, LLVM.CmpResult c ~ Bool, LLVM.IsSized c) =>
-   process a b ->
-   process (Value c, a) b
-quantizeLift = alter (\(Core next start stop) -> Core
-   (\context (k, a0) yState0 -> do
-      (yState1, frac1) <-
-         MaybeCont.fromBool $
-         C.whileLoop
-            (LLVM.valueOf True, yState0)
-            (\(cont1, (_, frac0)) ->
-               LLVM.and cont1 =<< A.fcmp LLVM.FPOLE frac0 A.zero)
-            (\(_,((_,state01), frac0)) ->
-               MaybeCont.toBool $ liftM2 (,)
-                  (next context a0 state01)
-                  (MaybeCont.lift $ A.add frac0 k))
-
-      frac2 <- MaybeCont.lift $ A.sub frac1 A.one
-      return (fst yState1, (yState1, frac2)))
-{- using this initialization code we would not need undefined values
-   (do sa <- start
-       (a,_) <- next sa
-       return (sa, a, A.zero))
--}
-   (\p -> do
-      s <- start p
-      return ((Tuple.undef, s), A.zero))
-   (\((_, s), _) -> stop s))
-
-
-
-foreign import ccall safe "dynamic" derefFillPtr ::
-   Exec.Importer
-      (LLVM.Ptr paramStruct -> Word -> Ptr a -> Ptr b -> IO Word)
-
-
-compile ::
-   (Storable.C a, Tuple.ValueOf a ~ aValue,
-    Storable.C b, Tuple.ValueOf b ~ bValue,
-    Memory.C param, Memory.Struct param ~ paramStruct,
-    Tuple.Phi state, Tuple.Undefined state) =>
-   (forall r z. (Tuple.Phi z) =>
-    param -> local -> aValue -> state -> MaybeCont.T r z (bValue, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r. param -> CodeGenFunction r state) ->
-   IO (LLVM.Ptr paramStruct -> Word -> Ptr a -> Ptr b -> IO Word)
-compile next alloca start =
-   Exec.compile "causal" $
-      Exec.createFunction derefFillPtr "fillprocessblock" $
-         \ paramPtr size alPtr blPtr -> do
-            param <- Memory.load paramPtr
-            s <- start param
-            local <- alloca
-            (pos,_) <-
-               Storable.arrayLoopMaybeCont2 size alPtr blPtr s $
-                  \ aPtri bPtri s0 -> do
-               a <- MaybeCont.lift $ Storable.load aPtri
-               (b,s1) <- next param local a s0
-               MaybeCont.lift $ Storable.store b bPtri
-               return s1
-            ret pos
-
-
-applyStorable ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T valueA valueB -> SV.Vector a -> SV.Vector b
-applyStorable proc = Unsafe.performIO $ runStorable proc
-
-runStorable ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T valueA valueB -> IO (SV.Vector a -> SV.Vector b)
-runStorable proc = (Unsafe.performIO .) <$> runStorableIO proc
-
-runStorableIO ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T valueA valueB -> IO (SV.Vector a -> IO (SV.Vector b))
-runStorableIO
-      (Cons next alloca start createIOContext deleteIOContext) = do
-
-   fill <- compile next alloca start
-   return $ \as ->
-      bracket createIOContext (deleteIOContext . fst) $ \ (_ioContext, params) ->
-         SVB.withStartPtr as $ \ aPtr len ->
-         SVB.createAndTrim len $ \ bPtr ->
-         Marshal.with params $ \paramPtr ->
-            fmap (fromIntegral :: Word -> Int) $
-            fill paramPtr (fromIntegral len) aPtr bPtr
-
-
-foreign import ccall safe "dynamic" derefStartPtr ::
-   Exec.Importer (LLVM.Ptr b -> IO (LLVM.Ptr a))
-
-foreign import ccall safe "dynamic" derefStopPtr ::
-   Exec.Importer (LLVM.Ptr a -> IO ())
-
-foreign import ccall safe "dynamic" derefChunkPtr ::
-   Exec.Importer
-      (LLVM.Ptr paramStruct -> LLVM.Ptr stateStruct -> Word ->
-       Ptr a -> Ptr b -> IO Word)
-
-
-compileChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ aValue,
-    Storable.C b, Tuple.ValueOf b ~ bValue,
-    Memory.C param, Memory.Struct param ~ paramStruct,
-    Memory.C state, Memory.Struct state ~ stateStruct) =>
-   (forall r z. (Tuple.Phi z) =>
-    param -> local -> aValue -> state -> MaybeCont.T r z (bValue, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r.
-    param -> CodeGenFunction r state) ->
-   IO (LLVM.Ptr paramStruct -> IO (LLVM.Ptr stateStruct),
-       Exec.Finalizer stateStruct,
-       LLVM.Ptr paramStruct -> LLVM.Ptr stateStruct ->
-       Word -> Ptr a -> Ptr b -> IO Word)
-compileChunky next alloca start =
-   Exec.compile "causal-chunky" $
-      liftA3 (,,)
-         (Exec.createFunction derefStartPtr "startprocess" $
-          \paramPtr -> do
-             pptr <- LLVM.malloc
-             param <- Memory.load paramPtr
-             flip Memory.store pptr =<< start param
-             ret pptr)
-         (Exec.createFinalizer derefStopPtr "stopprocess" $
-          \ pptr -> LLVM.free pptr >> ret ())
-         (Exec.createFunction derefChunkPtr "fillprocess" $
-          \paramPtr sptr loopLen aPtr bPtr -> do
-             sInit <- Memory.load sptr
-             param <- Memory.load paramPtr
-             local <- alloca
-             (pos,sExit) <-
-                Storable.arrayLoopMaybeCont2 loopLen aPtr bPtr sInit $
-                   \ aPtri bPtri s0 -> do
-                a <- MaybeCont.lift $ Storable.load aPtri
-                (b,s1) <- next param local a s0
-                MaybeCont.lift $ Storable.store b bPtri
-                return s1
-             Memory.store (Maybe.fromJust sExit) sptr
-             ret pos)
-
-
-traverseChunks ::
-   (Storable.C a, Storable.C b) =>
-   (LLVM.Ptr paramStruct -> LLVM.Ptr stateStruct ->
-    Word -> Ptr a -> Ptr b -> IO Word) ->
-   ForeignPtr.MemoryPtr paramStruct ->
-   ForeignPtr.MemoryPtr stateStruct ->
-   SVL.Vector a -> IO [SVB.Vector b]
-traverseChunks fill paramFPtr statePtr =
-   let go xt =
-          Unsafe.interleaveIO $
-          case xt of
-             [] -> return []
-             x:xs -> SVB.withStartPtr x $ \aPtr size -> do
-                v <-
-                   ForeignPtr.with paramFPtr $ \paramPtr ->
-                   ForeignPtr.with statePtr $ \sptr ->
-                   SVB.createAndTrim size $
-                      fmap (fromIntegral :: Word -> Int) .
-                      fill paramPtr sptr (fromIntegral size) aPtr
-                (if SV.length v > 0
-                   then fmap (v:)
-                   else id) $
-                   (if SV.length v < size
-                      then return []
-                      else go xs)
-   in  go . SVL.chunks
-
-
-runStorableChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T valueA valueB -> IO (SVL.Vector a -> SVL.Vector b)
-runStorableChunky
-      (Cons next alloca start createIOContext deleteIOContext) = do
-
-   (startFunc, stopFunc, fill) <- compileChunky next alloca start
-   return $ \sig -> SVL.fromChunks $ Unsafe.performIO $ do
-      (ioContext, params) <- createIOContext
-      paramPtr <- ForeignPtr.new (deleteIOContext ioContext) params
-      statePtr <-
-         ForeignPtr.newInit stopFunc $ ForeignPtr.with paramPtr startFunc
-      traverseChunks fill paramPtr statePtr sig
-
-
-applyStorableChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T valueA valueB -> SVL.Vector a -> SVL.Vector b
-applyStorableChunky = Unsafe.performIO . runStorableChunky
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Causal.Process (
+   Causal.T, MV,
+   CausalClass.fromSignal,
+   CausalClass.toSignal,
+   (CausalClass.$<), (CausalClass.$>), (CausalClass.$*),
+   ($<#), ($>#), ($*#),
+   map,
+   zipWith,
+   takeWhile,
+   take,
+   mix,
+   raise,
+   envelope,
+   envelopeStereo,
+   amplify,
+   amplifyStereo,
+   mapLinear,
+   mapExponential,
+   loop,
+   loopZero,
+   integrate,
+   integrateZero,
+   delay1,
+   delayControlled,
+   delayControlledInterpolated,
+   differentiate,
+   feedbackControlled,
+   feedbackControlledZero,
+   mapAccum,
+   fromModifier,
+   osciCoreSync,
+   osciCore,
+   osci,
+   shapeModOsci,
+   skip,
+   frequencyModulation,
+   frequencyModulationLinear,
+   Causal.quantizeLift,
+   track,
+   delay,
+   delayZero,
+   Causal.replicateControlled,
+   replicateControlledParam,
+   stereoFromMono,
+   stereoFromMonoControlled,
+   stereoFromMonoParameterized,
+   comb,
+   combStereo,
+   reverbExplicit,
+   reverbParams,
+   trigger,
+   arrayElement,
+   vectorize,
+   pipeline,
+   ) where
+
+import qualified Synthesizer.LLVM.Causal.Parameterized as Parameterized
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Private as SigPriv
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.RingBuffer as RingBuffer
+import qualified Synthesizer.LLVM.Interpolation as Interpolation
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Frame as Frame
+import Synthesizer.LLVM.Generator.Private (arraySize)
+import Synthesizer.LLVM.Private (noLocalPtr, unbool)
+
+import qualified Synthesizer.Plain.Modifier as Modifier
+import qualified Synthesizer.Causal.Class as CausalClass
+import Synthesizer.Causal.Class (($*), ($<))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Maybe as Maybe
+import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.Iterator as Iter
+import qualified LLVM.Extra.Control as C
+import qualified LLVM.Extra.Arithmetic as A
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+import Type.Data.Num.Decimal ((:<:))
+import Type.Base.Proxy (Proxy(Proxy))
+
+import qualified Data.List as List
+import Data.Traversable (sequenceA)
+import Data.Tuple.HT (mapSnd, swap)
+import Data.Word (Word)
+
+import qualified Control.Arrow as Arrow
+import qualified Control.Category as Cat
+import qualified Control.Monad.Trans.State as MS
+import qualified Control.Functor.HT as FuncHT
+import qualified Control.Applicative.HT as App
+import Control.Arrow (Arrow, arr, (<<<), (^<<), (<<^), (>>>), (***), (&&&))
+import Control.Applicative (pure, liftA2, liftA3, (<$>))
+
+import qualified System.Unsafe as Unsafe
+import System.Random (Random, RandomGen, randomR)
+
+import qualified Algebra.Additive as Additive
+import NumericPrelude.Numeric
+import NumericPrelude.Base hiding (map, zipWith, takeWhile, take)
+import Prelude ()
+
+
+type MV a b = Causal.T (MultiValue.T a) (MultiValue.T b)
+
+
+infixl 0 $<#, $>#, $*#
+
+{- |
+provide constant input in a comfortable way
+-}
+($*#) ::
+   (CausalClass.C process, CausalClass.SignalOf process ~ signal,
+    MultiValue.C a) =>
+   process (MultiValue.T a) b -> a -> signal b
+proc $*# x = CausalClass.applyConst proc $ MultiValue.cons x
+
+($<#) ::
+   (CausalClass.C process, MultiValue.C a) =>
+   process (MultiValue.T a, b) c -> a -> process b c
+proc $<# x = CausalClass.applyConstFst proc $ MultiValue.cons x
+
+($>#) ::
+   (CausalClass.C process, MultiValue.C b) =>
+   process (a, MultiValue.T b) c -> b -> process a c
+proc $># x = CausalClass.applyConstSnd proc $ MultiValue.cons x
+
+
+
+map ::
+   (Expr.Aggregate ae a, Expr.Aggregate be b) =>
+   (ae -> be) -> Causal.T a b
+map f = Causal.map (\a -> Expr.bundle (f (Expr.dissect a)))
+
+zipWith ::
+   (Expr.Aggregate ae a, Expr.Aggregate be b, Expr.Aggregate ce c) =>
+   (ae -> be -> ce) -> Causal.T (a,b) c
+zipWith f = map (uncurry f)
+
+takeWhile :: (Expr.Aggregate ae a) => (ae -> Exp Bool) -> Causal.T a a
+takeWhile p = Causal.simple
+   (\a () -> do
+      MaybeCont.guard . unbool =<< MaybeCont.lift (Expr.unliftM1 p a)
+      return (a,()))
+   (return ())
+
+take :: Exp Word -> Causal.T a a
+take len =
+   arr snd $< (takeWhile (0 Expr.<*) $* Sig.iterate (subtract 1) len)
+
+
+{- |
+You may also use '(+)'.
+-}
+mix :: (A.Additive a) => Causal.T (a,a) a
+mix = Causal.zipWith Frame.mix
+
+{- |
+You may also use '(+)' and a 'Sig.constant' signal or a number literal.
+-}
+raise :: (Marshal.C a, MultiValue.Additive a) => Exp a -> MV a a
+raise x = mix $< Sig.constant x
+
+
+{- |
+You may also use '(*)'.
+-}
+envelope :: (A.PseudoRing a) => Causal.T (a, a) a
+envelope = Causal.zipWith Frame.amplifyMono
+
+envelopeStereo :: (A.PseudoRing a) => Causal.T (a, Stereo.T a) (Stereo.T a)
+envelopeStereo = Causal.zipWith Frame.amplifyStereo
+
+{- |
+You may also use '(*)' and a 'Sig.constant' signal or a number literal.
+-}
+amplify ::
+   (Expr.Aggregate ea a, Memory.C a, A.PseudoRing a) =>
+   ea -> Causal.T a a
+amplify x = envelope $< Sig.constant x
+
+amplifyStereo ::
+   (Marshal.C a, MultiValue.PseudoRing a, Stereo.T (MultiValue.T a) ~ stereo) =>
+   Exp a -> Causal.T stereo stereo
+amplifyStereo x = envelopeStereo $< Sig.constant x
+
+
+mapLinear ::
+   (Marshal.C a, MultiValue.T a ~ am,
+    MultiValue.PseudoRing a, MultiValue.IntegerConstant a) =>
+   Exp a -> Exp a -> Causal.T am am
+mapLinear depth center = map (\x -> center + depth*x)
+
+-- ToDo: use base 2
+mapExponential ::
+   (Marshal.C a, MultiValue.T a ~ am,
+    MultiValue.Transcendental a, MultiValue.RationalConstant a) =>
+   Exp a -> Exp a -> Causal.T am am
+mapExponential depth center =
+   let logDepth = log depth
+   in map (\x -> center * exp (logDepth * x))
+
+
+loop ::
+   (Expr.Aggregate ce c, Memory.C c) =>
+   ce -> Causal.T (a,c) (b,c) -> Causal.T a b
+loop initial = Causal.loop (Expr.bundle initial)
+
+loopZero ::
+   (A.Additive c, Memory.C c) =>
+   Causal.T (a,c) (b,c) -> Causal.T a b
+loopZero = Causal.loop (return A.zero)
+
+loopConst ::
+   (Memory.C c) =>
+   c -> Causal.T (a,c) (b,c) -> Causal.T a b
+loopConst c = Causal.loop (return c)
+
+
+integrate ::
+   (Expr.Aggregate ae a, A.Additive a, Memory.C a) => ae -> Causal.T a a
+integrate initial = loop initial (arr snd &&& Causal.zipWith A.add)
+
+integrateZero :: (A.Additive a, Memory.C a) => Causal.T a a
+integrateZero = loopZero (arr snd &&& Causal.zipWith A.add)
+
+
+feedbackControlledAux ::
+   (Arrow arrow) =>
+   arrow ((ctrl,a),c) b ->
+   arrow (ctrl,b) c ->
+   arrow ((ctrl,a),c) (b,c)
+feedbackControlledAux forth back =
+   arr snd &&& back  <<<  arr (fst.fst) &&& forth
+
+feedbackControlled ::
+   (Expr.Aggregate ce c, Memory.C c) =>
+   ce -> Causal.T ((ctrl,a),c) b -> Causal.T (ctrl,b) c -> Causal.T (ctrl,a) b
+feedbackControlled initial forth back =
+   loop initial (feedbackControlledAux forth back)
+
+feedbackControlledZero ::
+   (A.Additive c, Memory.C c) =>
+   Causal.T ((ctrl,a),c) b -> Causal.T (ctrl,b) c -> Causal.T (ctrl,a) b
+feedbackControlledZero forth back =
+   loopZero (feedbackControlledAux forth back)
+
+
+arrayPtr ::
+   (TypeNum.Natural n, LLVM.IsSized a) =>
+   LLVM.Value (LLVM.Ptr a) ->
+   LLVM.CodeGenFunction r (LLVM.Value (LLVM.Ptr (LLVM.Array n a)))
+arrayPtr = LLVM.bitcast
+
+replicateControlledParam ::
+   (TypeNum.Natural n) =>
+   (Tuple.Undefined a, Tuple.Phi a) =>
+   (Marshal.C b, (n TypeNum.:*: LLVM.SizeOf (Marshal.Struct b)) ~ bSize,
+    TypeNum.Natural bSize) =>
+   (Exp b -> Causal.T (c,a) a) ->
+   Exp (MultiValue.Array n b) -> Causal.T (c,a) a
+replicateControlledParam f ps = Unsafe.performIO $ do
+   let n :: Word
+       n = TypeNum.integralFromProxy $ arraySize ps
+   paramd <- Parameterized.fromProcessPtr "Causal.replicateControlledParam" f
+   return $
+      case paramd of
+         Parameterized.Cons next start stop ->
+            Causal.Cons
+               (\(bPtr,globalPtr) localPtr (c,a0) statePtr -> do
+                  a1 <-
+                     MaybeCont.fromBool $
+                     Iter.mapWhileState_
+                        (\(biPtr,globalIPtr,localIPtr,stateIPtr)
+                              (_cont,ai0) -> do
+                           global <- Memory.load globalIPtr
+                           local <- Memory.load localIPtr
+                           state0 <- Memory.load stateIPtr
+                           (conti,(ai1,state1)) <-
+                              MaybeCont.toBool $
+                              next biPtr global local (c,ai0) state0
+                           flip LLVM.store stateIPtr =<< Memory.compose state1
+                           return (conti,(conti,ai1)))
+                        (Iter.take (LLVM.valueOf n) $
+                         App.lift4 (,,,)
+                           (Iter.arrayPtrs bPtr)
+                           (Iter.arrayPtrs globalPtr)
+                           (Iter.arrayPtrs localPtr)
+                           (Iter.arrayPtrs statePtr))
+                        (LLVM.valueOf True, a0)
+                  return (a1, statePtr))
+               (do
+                  bArr <- Expr.unExp ps
+                  bPtr <- LLVM.arrayMalloc n
+                  Memory.store bArr =<< arrayPtr bPtr
+                  {-
+                  ToDo:
+                  Instead of a pointer to a malloced with dynamic length
+                  we could use LLVM.Array.
+                  However, we would have to establish the constraint
+                  Natural (n :*: LLVM.SizeOf (Marshal.Struct a))
+                  This is pretty cumbersome
+                  with current decimal number representation.
+                  It would be feasible with type-level natural numbers, though.
+                  -}
+                  globalPtr <- LLVM.arrayMalloc n
+                  statePtr <- LLVM.arrayMalloc n
+                  Iter.mapM_
+                     (\(biPtr,globalIPtr,stateIPtr) -> do
+                        (global,state) <- start biPtr
+                        flip LLVM.store globalIPtr =<< Memory.compose global
+                        flip LLVM.store stateIPtr =<< Memory.compose state)
+                     (Iter.take (LLVM.valueOf n) $
+                      liftA3 (,,)
+                        (Iter.arrayPtrs bPtr)
+                        (Iter.arrayPtrs globalPtr)
+                        (Iter.arrayPtrs statePtr))
+                  return ((bPtr,globalPtr), statePtr))
+               (\(bPtr,globalPtr) ->
+                  Iter.mapM_
+                     (\(biPtr,globalIPtr) -> do
+                        stop biPtr =<< Memory.load globalIPtr)
+                     (Iter.take (LLVM.valueOf n) $
+                      liftA2 (,)
+                        (Iter.arrayPtrs bPtr)
+                        (Iter.arrayPtrs globalPtr)))
+
+
+{- |
+Run a causal process independently on each stereo channel.
+-}
+stereoFromMono ::
+   (Tuple.Phi a, Tuple.Undefined a, Tuple.Phi b, Tuple.Undefined b) =>
+   Causal.T a b -> Causal.T (Stereo.T a) (Stereo.T b)
+stereoFromMono proc =
+   snd
+   ^<<
+   Causal.replicateSerial 2
+      ((\((x,a),b) -> (Stereo.swap a, Stereo.cons (Stereo.right b) x))
+       ^<<
+       Arrow.first ((proc <<^ Stereo.left) &&& Cat.id))
+   <<^
+   (\a -> (a, Tuple.undef))
+
+stereoFromMonoControlled ::
+   (Tuple.Phi a, Tuple.Phi b, Tuple.Phi c,
+    Tuple.Undefined a, Tuple.Undefined b, Tuple.Undefined c) =>
+   Causal.T (c,a) b -> Causal.T (c, Stereo.T a) (Stereo.T b)
+stereoFromMonoControlled proc =
+   stereoFromMono proc <<^ (\(c,sa) -> (,) c <$> sa)
+
+arrayFromStereo ::
+   (Marshal.C a) =>
+   Stereo.T (MultiValue.T a) ->
+   LLVM.CodeGenFunction r (MultiValue.T (MultiValue.Array TypeNum.D2 a))
+arrayFromStereo a =
+   MultiValue.insertArrayValue TypeNum.d0 (Stereo.left a) =<<
+   MultiValue.insertArrayValue TypeNum.d1 (Stereo.right a) MultiValue.undef
+
+stereoFromMonoParameterized ::
+   (Marshal.C x,
+    Tuple.Phi a, Tuple.Undefined a, Tuple.Phi b, Tuple.Undefined b) =>
+   ((TypeNum.D2 TypeNum.:*: LLVM.SizeOf (Marshal.Struct x)) ~ xSize,
+    TypeNum.Natural xSize) =>
+   (Exp x -> Causal.T a b) ->
+   Stereo.T (Exp x) -> Causal.T (Stereo.T a) (Stereo.T b)
+stereoFromMonoParameterized f sx =
+   snd
+   ^<<
+   replicateControlledParam
+      (\x ->
+         (\((y,a),b) -> (Stereo.swap a, Stereo.cons (Stereo.right b) y))
+         ^<<
+         Arrow.first ((f x <<^ Stereo.left) &&& Cat.id)
+         <<^
+         snd)
+      (Expr.liftM arrayFromStereo sx)
+   <<^
+   (\a -> ((),(a,Tuple.undef)))
+
+
+mapAccum ::
+   (Expr.Aggregate state statel, Memory.C statel,
+    Expr.Aggregate a al, Expr.Aggregate b bl) =>
+   (a -> state -> (b, state)) -> state -> Causal.T al bl
+mapAccum next start =
+   Causal.mapAccum
+      (\a s -> Expr.bundle $ next (Expr.dissect a) (Expr.dissect s))
+      (Expr.bundle start)
+
+fromModifier ::
+   (Expr.Aggregate ae al,
+    Expr.Aggregate be bl,
+    Expr.Aggregate ce cl,
+    Expr.Aggregate se sl, Memory.C sl) =>
+   Modifier.Simple se ce ae be -> Causal.T (cl,al) bl
+fromModifier (Modifier.Simple initial step) =
+   mapAccum (\(c,a) -> MS.runState (step c a)) initial
+
+
+delay1 :: (Expr.Aggregate ae a, Memory.C a) => ae -> Causal.T a a
+delay1 initial  =  loop initial (arr swap)
+
+differentiate ::
+   (A.Additive a, Expr.Aggregate ae a, Memory.C a) => ae -> Causal.T a a
+differentiate initial  =  Cat.id - delay1 initial
+
+
+{- |
+Compute the phases from phase distortions and frequencies.
+
+It's like integrate but with wrap-around performed by @fraction@.
+For FM synthesis we need also negative phase distortions,
+thus we use 'A.addToPhase' which supports that.
+-}
+osciCore, _osciCore, osciCoreSync ::
+   (Memory.C t, A.Fraction t) => Causal.T (t, t) t
+_osciCore =
+   Causal.zipWith A.addToPhase <<<
+   Arrow.second
+      (Causal.mapAccum
+         (\a s -> do
+            b <- A.incPhase a s
+            return (s,b))
+         (return A.zero))
+
+{-
+This could be implemented using a generalized frequencyModulation,
+however, osciCoreSync allows for negative phase differences.
+-}
+osciCoreSync =
+   Causal.zipWith A.addToPhase <<<
+   Arrow.second
+      (Causal.mapAccum
+         (\a s -> do
+            b <- A.incPhase a s
+            return (b,b))
+         (return A.zero))
+
+osciCore =
+   Causal.zipWith A.addToPhase <<<
+   Arrow.second (loopZero (arr snd &&& Causal.zipWith A.incPhase))
+
+osci ::
+   (Memory.C t, A.Fraction t) =>
+   (forall r. t -> LLVM.CodeGenFunction r y) ->
+   Causal.T (t, t) y
+osci wave  =  Causal.map wave <<< osciCore
+
+shapeModOsci ::
+   (Memory.C t, A.Fraction t) =>
+   (forall r. c -> t -> LLVM.CodeGenFunction r y) ->
+   Causal.T (c, (t, t)) y
+shapeModOsci wave  =  Causal.zipWith wave <<< Arrow.second osciCore
+
+
+{- |
+Feeds a signal into a causal process while holding or skipping signal elements
+according to the process input.
+The skip happens after a value is passed from the fed signal.
+
+@skip x $* 0@ repeats the first signal value in the output.
+@skip x $* 1@ feeds the signal to the output as is.
+@skip x $* 2@ feeds the signal to the output with double speed.
+-}
+skip ::
+   (Tuple.Undefined a, Tuple.Phi a, Memory.C a) =>
+   Sig.T a -> Causal.T (MultiValue.T Word) a
+skip (SigPriv.Cons next start stop) = Causal.Cons
+   (\global local n1 (yState0, MultiValue.Cons n0) -> do
+      yState1@(y,_) <-
+         MaybeCont.fromMaybe $ fmap snd $
+         MaybeCont.fixedLengthLoop n0 yState0 $
+         next global local . snd
+      return (y, (yState1,n1)))
+   (mapSnd (\s -> ((Tuple.undef, s), A.one)) <$> start)
+   stop
+
+frequencyModulation ::
+   (Marshal.C a,
+    MultiValue.IntegerConstant a,
+    MultiValue.Additive a,
+    MultiValue.Comparison a,
+    Tuple.Undefined nodes, Tuple.Phi nodes, Memory.C nodes) =>
+   (forall r. MultiValue.T a -> nodes -> LLVM.CodeGenFunction r v) ->
+   SigPriv.T nodes -> Causal.T (MultiValue.T a) v
+frequencyModulation ip (SigPriv.Cons next start stop) = Causal.Cons
+   (\global local k yState0 -> do
+      ((nodes2,state2), ss2) <-
+         MaybeCont.fromBool $
+         C.whileLoop
+            (LLVM.valueOf True, yState0)
+            (\(cont0, (_, ss0)) ->
+               LLVM.and cont0 . unbool =<< MultiValue.cmp LLVM.CmpGE ss0 A.one)
+            (\(_,((_,state0), ss0)) ->
+               MaybeCont.toBool $ liftA2 (,)
+                  (next global local state0)
+                  (MaybeCont.lift $ A.sub ss0 A.one))
+
+      MaybeCont.lift $ do
+         y <- ip ss2 nodes2
+         ss3 <- A.add ss2 k
+         return (y, ((nodes2, state2), ss3)))
+   (fmap (\(global,sa) -> (global, ((Tuple.undef, sa), A.one))) start)
+   stop
+
+frequencyModulationLinear ::
+   (MultiValue.PseudoRing a, MultiValue.IntegerConstant a,
+    MultiValue.Comparison a, Marshal.C a) =>
+   Sig.MV a -> MV a a
+frequencyModulationLinear sig =
+   frequencyModulation Interpolation.linear (Sig.adjacentNodes02 sig)
+
+
+track ::
+   (Expr.Aggregate ae al, Memory.C al) =>
+   ae -> Exp Word -> Causal.T al (RingBuffer.T al)
+track initial time = Causal.Cons
+   (\(size0,ptr) -> noLocalPtr $ \a remain0 -> MaybeCont.lift $ do
+      Memory.store a =<< LLVM.getElementPtr ptr (remain0, ())
+      cont <- A.cmp LLVM.CmpGT remain0 A.zero
+      remain1 <- C.ifThenSelect cont size0 (A.dec remain0)
+      size1 <- A.inc size0
+      return (RingBuffer.Cons ptr size1 remain0 remain1, remain1))
+   (do
+      MultiValue.Cons size0 <- Expr.unExp time
+      size1 <- A.inc size0
+      ptr <- LLVM.arrayMalloc size1
+      a <- Expr.bundle initial
+      -- cf. LLVM.Storable.Signal.fill
+      C.arrayLoop size1 ptr () $ \ ptri () -> Memory.store a ptri
+      return ((size0,ptr), size0))
+   (LLVM.free . snd)
+
+{- |
+Delay time must be non-negative.
+-}
+delay ::
+   (Expr.Aggregate ae al, Memory.C al) =>
+   ae -> Exp Word -> Causal.T al al
+delay initial time = Causal.map RingBuffer.oldest <<< track initial time
+
+delayZero ::
+   (Expr.Aggregate ae al, Additive.C ae, Memory.C al) =>
+   Exp Word -> Causal.T al al
+delayZero = delay zero
+
+{- |
+Delay time must be greater than zero!
+-}
+comb ::
+   (Marshal.C a, MultiValue.PseudoRing a) =>
+   Exp a -> Exp Word -> MV a a
+comb gain time =
+   loopZero (mix >>> (Cat.id &&& (delayZero (time-1) >>> amplify gain)))
+
+combStereo ::
+   (Marshal.C a, MultiValue.PseudoRing a, Stereo.T (MultiValue.T a) ~ stereo) =>
+   Exp a -> Exp Word -> Causal.T stereo stereo
+combStereo gain time =
+   loopZero (mix >>> (Cat.id &&& (delayZero (time-1) >>> amplifyStereo gain)))
+
+reverbExplicit ::
+   (TypeNum.Natural n, (n TypeNum.:*: LLVM.UnknownSize) ~ paramSize,
+    TypeNum.Natural paramSize) =>
+   (Marshal.C a,
+    MultiValue.Field a, MultiValue.Real a, MultiValue.IntegerConstant a) =>
+   Exp (MultiValue.Array n (a,Word)) -> MV a a
+reverbExplicit params =
+   amplify (Expr.recip $ TypeNum.integralFromProxy $ arraySize params)
+   <<<
+   replicateControlledParam
+      (\p -> Arrow.first (comb (Expr.fst p) (Expr.snd p)) >>> mix)
+      params
+   <<^
+   (\a -> (a,a))
+
+reverbParams ::
+   (RandomGen g, TypeNum.Integer n, Random a) =>
+   g -> Proxy n -> (a,a) -> (Word, Word) -> MultiValue.Array n (a, Word)
+reverbParams rnd Proxy gainRange timeRange =
+   flip MS.evalState rnd $
+   sequenceA $ pure $
+   liftA2 (,)
+      (MS.state (randomR gainRange))
+      (MS.state (randomR timeRange))
+
+
+{- |
+Delay by a variable amount of samples.
+The momentum delay must be between @0@ and @maxTime@, inclusively.
+How about automated clipping?
+-}
+delayControlled ::
+   (Expr.Aggregate ae al, Memory.C al) =>
+   ae -> Exp Word -> Causal.T (MultiValue.T Word, al) al
+delayControlled initial maxTime =
+   Causal.zipWith RingBuffer.index
+   <<<
+   arr (\(MultiValue.Cons i) -> i) *** track initial maxTime
+
+{- |
+Delay by a variable fractional amount of samples.
+Non-integer delays are achieved by interpolation.
+The momentum delay must be between @0@ and @maxTime@, inclusively.
+-}
+delayControlledInterpolated ::
+   (Interpolation.C nodes) =>
+   (MultiValue.T a ~ am) =>
+   (MultiValue.NativeFloating a ar, MultiValue.Additive a) =>
+   (Expr.Aggregate ve v, Memory.C v) =>
+   (forall r. Interpolation.T r nodes am v) ->
+   ve -> Exp Word -> Causal.T (am, v) v
+delayControlledInterpolated ip initial maxTime =
+   let margin = Interpolation.toMargin ip
+   in Causal.zipWith
+         (\del buf -> do
+            let offset =
+                  A.fromInteger' $ fromIntegral $
+                  Interpolation.marginOffset margin
+            n <- A.max offset =<< MultiValue.truncateToInt del
+            k <- A.sub del =<< MultiValue.fromIntegral n
+            ~(MultiValue.Cons m) <- A.sub n (offset :: MultiValue.T Word)
+            ip k =<<
+               Interpolation.indexNodes (flip RingBuffer.index buf) A.one m)
+      <<<
+      Arrow.second
+         (track initial
+             (fromIntegral (Interpolation.marginNumber margin) + maxTime))
+
+
+{- |
+This allows to compute a chain of equal processes efficiently,
+if all of these processes can be bundled in one vectorial process.
+Applications are an allpass cascade or an FM operator cascade.
+
+The function expects that the vectorial input process
+works like parallel scalar processes.
+The different pipeline stages may be controlled by different parameters,
+but the structure of all pipeline stages must be equal.
+Our function feeds the input of the pipelined process
+to the zeroth element of the Vector.
+The result of processing the i-th element (the i-th channel, so to speak)
+is fed to the (i+1)-th element.
+The (n-1)-th element of the vectorial process is emitted
+as output of the pipelined process.
+
+The pipeline necessarily introduces a delay of (n-1) values.
+For simplification we extend this to n values delay.
+If you need to combine the resulting signal from the pipeline
+with another signal in a 'zip'-like way,
+you may delay that signal with @pipeline id@.
+The first input values in later stages of the pipeline
+are initialized with zero.
+If this is not appropriate for your application,
+then we may add a more sensible initialization.
+-}
+pipeline ::
+   (TypeNum.Positive n, MultiVector.C x,
+    v ~ MultiVector.T n x,
+    a ~ MultiValue.T x,
+    Tuple.Zero v, Memory.C v) =>
+   Causal.T v v -> Causal.T a a
+pipeline vectorProcess =
+   loopConst MultiVector.zero $
+      Causal.map (uncurry MultiVector.shiftUp)
+      >>>
+      Arrow.second vectorProcess
+
+
+{-
+insert and extract instructions will be in opposite order,
+no matter whether we use foldr or foldl
+and independent from the order of proc and channel in replaceChannel.
+However, LLVM neglects the order anyway.
+-}
+vectorize ::
+   (TypeNum.Positive n,
+    MultiVector.C x, MultiValue.T x ~ a, MultiVector.T n x ~ va,
+    MultiVector.C y, MultiValue.T y ~ b, MultiVector.T n y ~ vb) =>
+   Causal.T a b -> Causal.T va vb
+vectorize proc =
+   withSize $ \n ->
+      foldl
+         (\acc i -> replaceChannel i proc acc)
+         (arr (const Tuple.undef)) $
+      List.take (TypeNum.integralFromSingleton n) [0 ..]
+
+withSize ::
+   (TypeNum.Positive n, MultiVector.T n a ~ v) =>
+   (TypeNum.Singleton n -> f v) ->
+   f v
+withSize f = f TypeNum.singleton
+
+{- |
+Given a vector process, replace the i-th output by output
+that is generated by a scalar process from the i-th input.
+-}
+replaceChannel ::
+   (TypeNum.Positive n,
+    MultiVector.C x, MultiValue.T x ~ a, MultiVector.T n x ~ va,
+    MultiVector.C y, MultiValue.T y ~ b, MultiVector.T n y ~ vb) =>
+   Int -> Causal.T a b -> Causal.T va vb -> Causal.T va vb
+replaceChannel i channel proc =
+   let li = LLVM.valueOf $ fromIntegral i
+   in Causal.zipWith (MultiVector.insert li) <<<
+         (channel <<< Causal.map (MultiVector.extract li)) &&&
+         proc
+
+
+{- |
+Read the i-th element from each array.
+-}
+arrayElement ::
+   (Marshal.C a, Marshal.Struct a ~ aStruct, LLVM.IsFirstClass aStruct,
+    TypeNum.Natural i, TypeNum.Natural n, i :<: n) =>
+   Proxy i -> Causal.T (MultiValue.T (MultiValue.Array n a)) (MultiValue.T a)
+arrayElement i = Causal.map (MultiValue.extractArrayValue i)
+
+
+{- |
+@trigger fill signal@ sends @signal@ to the output
+and restarts it whenever the process input is 'Just'.
+Before the Arrow.first occurrence of 'Just'
+and between instances of the signal the output is filled with 'Maybe.nothing'.
+-}
+trigger ::
+   (Marshal.C a, Tuple.Undefined b, Tuple.Phi b) =>
+   (Exp a -> Sig.T b) ->
+   Causal.T (Maybe.T (MultiValue.T a)) (Maybe.T b)
+trigger f = Unsafe.performIO $ do
+   paramd <-
+      Parameterized.fromProcess "Causal.trigger" (CausalClass.fromSignal . f)
+   return $
+      case paramd of
+         Parameterized.Cons next start stop -> Causal.Cons
+            (\globalPtr local ma ms0 -> MaybeCont.lift $ do
+               ms1 <-
+                  Maybe.run ma
+                     (return ms0)
+                     (\a -> do
+                        stopAndFree stop globalPtr
+                        (global2,state2) <- start a
+                        Memory.store (Maybe.just (a,global2)) globalPtr
+                        return $ Maybe.just state2)
+               mc1 <- Memory.load globalPtr
+               mcs1 <- Maybe.lift2 (,) mc1 ms1
+               as2 <-
+                  Maybe.run mcs1 (return Maybe.nothing) $ \((p1,c1),s1) ->
+                     MaybeCont.toMaybe $ next p1 c1 local () s1
+               return $ FuncHT.unzip as2)
+            (do
+               globalPtr <- LLVM.malloc
+               Memory.store (nothingFromFunc f stop) globalPtr
+               return (globalPtr, Maybe.nothing))
+            (\globalPtr -> do
+               stopAndFree stop globalPtr
+               LLVM.free globalPtr)
+
+stopAndFree ::
+   (Memory.C global, Memory.C am) =>
+   (am -> global -> LLVM.CodeGenFunction r ()) ->
+   LLVM.Value (LLVM.Ptr (Memory.Struct (Maybe.T (am, global)))) ->
+   LLVM.CodeGenFunction r ()
+stopAndFree stop globalPtr = do
+   maybeGlobal <- Memory.load globalPtr
+   Maybe.for maybeGlobal $ \(a,global) -> stop a global
+
+nothingFromFunc ::
+   (MultiValue.C a, Tuple.Undefined global) =>
+   (Exp a -> Sig.T b) ->
+   (ap -> global -> code) ->
+   Maybe.T (MultiValue.T a, global)
+nothingFromFunc _ _ = Maybe.nothing
diff --git a/src/Synthesizer/LLVM/Causal/ProcessPacked.hs b/src/Synthesizer/LLVM/Causal/ProcessPacked.hs
--- a/src/Synthesizer/LLVM/Causal/ProcessPacked.hs
+++ b/src/Synthesizer/LLVM/Causal/ProcessPacked.hs
@@ -1,76 +1,83 @@
-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
 module Synthesizer.LLVM.Causal.ProcessPacked where
 
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
 import qualified Synthesizer.LLVM.Causal.Process as Causal
-import Synthesizer.LLVM.Causal.ProcessPrivate (Core(Core), alter)
-
 import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as SerialCode
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as SerialClass
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Frame as Frame
 
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.MaybeContinuation as Maybe
-import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.MaybeContinuation as Maybe
 import qualified LLVM.Extra.Control as C
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-          (CodeGenFunction, Value, valueOf,
-           IsSized, IsFirstClass)
+import qualified LLVM.Extra.Arithmetic as A
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal ((:<:))
 import Type.Base.Proxy (Proxy)
 
+import qualified LLVM.Core as LLVM
+
+import qualified Control.Arrow as Arrow
+import qualified Control.Category as Cat
 import qualified Control.Monad.Trans.Class as MT
 import qualified Control.Monad.Trans.State as MS
-import qualified Control.Arrow as Arr
 import Control.Arrow ((<<<))
 
+import Data.Tuple.HT (swap)
 import Data.Word (Word)
 
 import NumericPrelude.Numeric
-import NumericPrelude.Base
+import NumericPrelude.Base hiding (map, zipWith, takeWhile)
+import Prelude ()
 
 
+type Serial n a = MultiValue.T (Serial.T n a)
+
+
 {- |
 Run a scalar process on packed data.
 If the signal length is not divisible by the chunk size,
 then the last chunk is dropped.
 -}
 pack ::
-   (Causal.C process,
-    Serial.Read va, n ~ Serial.Size va, a ~ Serial.Element va,
-    Serial.C    vb, n ~ Serial.Size vb, b ~ Serial.Element vb) =>
-   process a b -> process va vb
-pack = alter (\(Core next start stop) -> Core
-   (\param a s -> do
-      r <- Maybe.lift $ Serial.readStart a
+   (SerialClass.Read  va, n ~ SerialClass.Size va, a ~ SerialClass.Element va,
+    SerialClass.Write vb, n ~ SerialClass.Size vb, b ~ SerialClass.Element vb)
+   =>
+   Causal.T a b -> Causal.T va vb
+pack (CausalPriv.Cons next start stop) = CausalPriv.Cons
+   (\global local a s -> do
+      r <- Maybe.lift $ SerialClass.readStart a
       ((_,w2),(_,s2)) <-
          Maybe.fromBool $
          C.whileLoop
-            (valueOf True,
+            (LLVM.valueOf True,
              let w = Tuple.undef
-             in  ((r,w),
-                  (valueOf (fromIntegral $ Serial.sizeOfIterator w :: Word), s)))
+             in ((r,w),
+                 (LLVM.valueOf (SerialClass.sizeOfIterator w :: Word), s)))
             (\(cont,(_rw0,(i0,_s0))) ->
-               A.and cont =<<
-                  A.cmp LLVM.CmpGT i0 A.zero)
+               A.and cont =<< A.cmp LLVM.CmpGT i0 A.zero)
             (\(_,((r0,w0),(i0,s0))) -> Maybe.toBool $ do
-               (ai,r1) <- Maybe.lift $ Serial.readNext r0
-               (bi,s1) <- next param ai s0
+               (ai,r1) <- Maybe.lift $ SerialClass.readNext r0
+               (bi,s1) <- next global local ai s0
                Maybe.lift $ do
-                  w1 <- Serial.writeNext bi w0
+                  w1 <- SerialClass.writeNext bi w0
                   i1 <- A.dec i0
                   return ((r1,w1),(i1,s1)))
-      b <- Maybe.lift $ Serial.writeStop w2
+      b <- Maybe.lift $ SerialClass.writeStop w2
       return (b, s2))
    start
-   stop)
+   stop
 
 {- |
 Like 'pack' but duplicates the code for the scalar process.
@@ -79,100 +86,95 @@
 This is efficient only for simple input processes.
 -}
 packSmall ::
-   (Causal.C process,
-    Serial.Read va, n ~ Serial.Size va, a ~ Serial.Element va,
-    Serial.C    vb, n ~ Serial.Size vb, b ~ Serial.Element vb) =>
-   process a b -> process va vb
-packSmall = alter (\(Core next start stop) -> Core
-   (\param a ->
+   (SerialClass.Read  va, n ~ SerialClass.Size va, a ~ SerialClass.Element va,
+    SerialClass.Write vb, n ~ SerialClass.Size vb, b ~ SerialClass.Element vb)
+   =>
+   Causal.T a b -> Causal.T va vb
+packSmall (CausalPriv.Cons next start stop) = CausalPriv.Cons
+   (\global local a ->
       MS.runStateT $
-         (MT.lift . Maybe.lift . Serial.assemble)
+         MT.lift . Maybe.lift . SerialClass.assemble
          =<<
-         mapM (MS.StateT . next param)
+         mapM (MS.StateT . next global local)
          =<<
-         (MT.lift $ Maybe.lift $ Serial.extractAll a))
+         (MT.lift $ Maybe.lift $ SerialClass.dissect a))
    start
-   stop)
+   stop
 
 
-{- |
-Run a packed process on scalar data.
-If the signal length is not divisible by the chunk size,
-then the last chunk is dropped.
-In order to stay causal, we have to delay the output by @n@ samples.
--}
-unpack ::
-   (Causal.C process,
-    Serial.Zero va, n ~ Serial.Size va, a ~ Serial.Element va,
-    Serial.Read vb, n ~ Serial.Size vb, b ~ Serial.Element vb,
-    Memory.C va, Memory.C ita, ita ~ Serial.WriteIt va,
-    Memory.C vb, Memory.C itb, itb ~ Serial.ReadIt vb) =>
-   process va vb -> process a b
-unpack = alter (\(Core next start stop) -> Core
-   (\param ai ((w0,r0),(i0,s0)) -> do
-      endOfVector <- Maybe.lift $ A.cmp LLVM.CmpEQ i0 A.zero
-      ((w2,r2),(i2,s2)) <-
-         Maybe.fromBool $
-         C.ifThen endOfVector (valueOf True, ((w0,r0),(i0,s0))) $ do
-            a0 <- Serial.writeStop w0
-            (cont1, (b1,s1)) <- Maybe.toBool $ next param a0 s0
-            r1 <- Serial.readStart b1
-            w1 <- Serial.writeStart
-            return (cont1,
-                      ((w1, r1),
-                       (valueOf $ fromIntegral $ Serial.size a0, s1)))
-      Maybe.lift $ do
-         w3 <- Serial.writeNext ai w2
-         (bi,r3) <- Serial.readNext r2
-         i3 <- A.dec i2
-         return (bi, ((w3,r3),(i3,s2))))
-   (\s -> do
-      s1 <- start s
-      w <- Serial.writeZero
-      return ((w, Tuple.undef), (valueOf (0::Word), s1)))
-   (\(_wr,(_i,state)) -> stop state))
+raise ::
+   (TypeNum.Positive n, MultiVector.Additive a) =>
+   Exp a -> Causal.T (Serial n a) (Serial n a)
+raise x =
+   CausalPriv.map
+      (\y -> Expr.unExp (Serial.upsample x) >>= flip Frame.mix y)
 
+amplify ::
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   Exp a -> Causal.T (Serial n a) (Serial n a)
+amplify x =
+   CausalPriv.map
+      (\y -> Expr.unExp (Serial.upsample x) >>= flip Frame.amplifyMono y)
 
+amplifyStereo ::
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   Exp a -> Causal.T (Stereo.T (Serial n a)) (Stereo.T (Serial n a))
+amplifyStereo x =
+   CausalPriv.map
+      (\y -> Expr.unExp (Serial.upsample x) >>= flip Frame.amplifyStereo y)
+
+
+delay1 ::
+   (LLVM.Positive n, Marshal.C a,
+    MultiVector.C a, SerialCode.Value n a ~ v) =>
+   Exp a -> Causal.T v v
+delay1 initial =
+   Causal.loop initial $
+   Causal.map (swap . uncurry Serial.shiftUp . swap)
+
+differentiate ::
+   (LLVM.Positive n, Marshal.C a,
+    MultiVector.Additive a, SerialCode.Value n a ~ v) =>
+   Exp a -> Causal.T v v
+differentiate initial = Cat.id - delay1 initial
+
+integrate ::
+   (LLVM.Positive n, Marshal.C a,
+    MultiVector.Additive a, SerialCode.Value n a ~ v) =>
+   Exp a -> Causal.T v v
+integrate =
+   Causal.mapAccum (\a acc0 -> swap $ Serial.cumulate acc0 a)
+
+
 osciCore ::
-   (Causal.C process,
-    IsSized t, Vector.Real t, SoV.Fraction t, LLVM.IsFloating t,
-    TypeNum.Positive n) =>
-   process (Serial.Value n t, Serial.Value n t) (Serial.Value n t)
+   (TypeNum.Positive n, Marshal.C t, MultiVector.Fraction t) =>
+   Causal.T (Serial n t, Serial n t) (Serial n t)
 osciCore =
-   Causal.zipWith A.addToPhase <<<
-   Arr.second
+   CausalPriv.zipWith A.addToPhase <<<
+   Arrow.second
       (Causal.mapAccum
-         (\a phase0 -> do
-            (phase1,b1) <- Serial.cumulate phase0 a
-            phase2 <- A.signedFraction phase1
-            return (b1,phase2))
-         (return A.zero))
+         (\a phase0 ->
+            let (phase1,b1) = Serial.cumulate phase0 a
+            in (b1, Expr.liftM A.signedFraction phase1))
+         Expr.zero)
 
 osci ::
-   (Causal.C process,
-    IsSized t, Vector.Real t, SoV.Fraction t, LLVM.IsFloating t,
-    TypeNum.Positive n) =>
-   (forall r. Serial.Value n t -> CodeGenFunction r y) ->
-   process (Serial.Value n t, Serial.Value n t) y
-osci wave =
-   Causal.map wave <<< osciCore
+   (TypeNum.Positive n, Marshal.C t, MultiVector.Fraction t) =>
+   (forall r. Serial n t -> LLVM.CodeGenFunction r y) ->
+   Causal.T (Serial n t, Serial n t) y
+osci wave = CausalPriv.map wave <<< osciCore
 
 shapeModOsci ::
-   (Causal.C process,
-    IsSized t, Vector.Real t, SoV.Fraction t, LLVM.IsFloating t,
-    TypeNum.Positive n) =>
-   (forall r. c -> Serial.Value n t -> CodeGenFunction r y) ->
-   process (c, (Serial.Value n t, Serial.Value n t)) y
-shapeModOsci wave =
-   Causal.zipWith wave <<< Arr.second osciCore
-
+   (TypeNum.Positive n, Marshal.C t, MultiVector.Fraction t) =>
+   (forall r. c -> Serial n t -> LLVM.CodeGenFunction r y) ->
+   Causal.T (c, (Serial n t, Serial n t)) y
+shapeModOsci wave = CausalPriv.zipWith wave <<< Arrow.second osciCore
 
 
 arrayElement ::
-   (Causal.C process,
-    IsFirstClass a, LLVM.Value a ~ Serial.Element v, Serial.C v,
-    TypeNum.Natural index, TypeNum.Natural dim,
-    index :<: dim) =>
-   Proxy index -> process (Value (LLVM.Array dim a)) v
-arrayElement i =
-   Causal.map Serial.upsample <<< Causal.arrayElement i
+   (TypeNum.Positive n,
+    MultiVector.C a, Marshal.C a,
+    Marshal.Struct a ~ aStruct, LLVM.IsFirstClass aStruct,
+    TypeNum.Natural i, TypeNum.Natural d, i :<: d) =>
+   Proxy i -> Causal.T (MultiValue.T (MultiValue.Array d a)) (Serial n a)
+arrayElement i = Causal.map Serial.upsample <<< Causal.arrayElement i
diff --git a/src/Synthesizer/LLVM/Causal/ProcessPrivate.hs b/src/Synthesizer/LLVM/Causal/ProcessPrivate.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Causal/ProcessPrivate.hs
+++ /dev/null
@@ -1,306 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.Causal.ProcessPrivate where
-
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as Sig
-import qualified Synthesizer.Causal.Class as CausalClass
-import qualified Synthesizer.Causal.Utility as ArrowUtil
-
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-
-import LLVM.Core (CodeGenFunction, Value)
-
-import System.Random (Random, RandomGen, randomR)
-
-import qualified Control.Arrow    as Arr
-import qualified Control.Category as Cat
-import qualified Control.Monad.Trans.State as MS
-import Control.Arrow (Arrow, arr, (<<<), (>>>), (&&&))
-import Control.Monad (liftM2, replicateM)
-import Control.Applicative (Applicative, pure, (<*>))
-
-import qualified Number.Ratio as Ratio
-import qualified Algebra.Field as Field
-import qualified Algebra.Ring as Ring
-import qualified Algebra.Additive as Additive
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base hiding (and, map, zip, zipWith, init)
-
-import qualified Prelude as P
-
-
-data Core context initState exitState a b =
-   forall state.
-      (Memory.C state) =>
-      Core (forall r c.
-            (Tuple.Phi c) =>
-            context ->
-            a -> state -> MaybeCont.T r c (b, state))
-               -- compute next value
-           (forall r.
-            initState ->
-            CodeGenFunction r state)
-               -- initial state
-           (state -> exitState)
-               -- extract final state for cleanup
-
-
-class
-   (CausalClass.C process, Sig.C (CausalClass.SignalOf process)) =>
-      C process where
-   simple ::
-      (Memory.C state) =>
-      (forall r c.
-       (Tuple.Phi c) =>
-       a -> state -> MaybeCont.T r c (b, state)) ->
-      (forall r. CodeGenFunction r state) ->
-      process a b
-
-   alter ::
-      (forall contextLocal initState exitState.
-          Core contextLocal initState exitState a0 b0 ->
-          Core contextLocal initState exitState a1 b1) ->
-      process a0 b0 -> process a1 b1
-
-   replicateControlled ::
-      (Tuple.Undefined x, Tuple.Phi x) =>
-      Int -> process (c,x) x -> process (c,x) x
-
-
-alterSignal ::
-   (C process, CausalClass.SignalOf process ~ signal) =>
-   (forall contextLocal initState exitState.
-       Sig.Core contextLocal initState exitState a0 ->
-       Core contextLocal initState exitState a1 b1) ->
-   signal a0 -> process a1 b1
-alterSignal f =
-   alter (\(Core next start stop) -> f (Sig.Core (\c -> next c ()) start stop))
-   .
-   CausalClass.fromSignal
-
-
-
-data T a b =
-   forall state local ioContext parameters.
-      (Marshal.C parameters, Memory.C state) =>
-      Cons (forall r c.
-            (Tuple.Phi c) =>
-            Tuple.ValueOf parameters -> local ->
-            a -> state -> MaybeCont.T r c (b, state))
-               -- compute next value
-           (forall r.
-            CodeGenFunction r local)
-               -- allocate temporary variables before a loop
-           (forall r.
-            Tuple.ValueOf parameters ->
-            CodeGenFunction r state)
-               -- initial state
-           (IO (ioContext, parameters))
-               -- initialization from IO monad
-           (ioContext -> IO ())
-               -- finalization from IO monad
-
-
-type instance CausalClass.ProcessOf Sig.T = T
-
-instance CausalClass.C T where
-   type SignalOf T = Sig.T
-   toSignal = toSignal
-   fromSignal = fromSignal
-
-instance C T where
-   simple next start =
-      Cons
-         (const $ \ () -> next)
-         (return ())
-         (const start)
-         (return ((),()))
-         (const $ return ())
-
-   alter f (Cons next0 alloca start0 create delete) =
-      case f (Core (uncurry next0) start0 id) of
-         Core next1 start1 _ ->
-            Cons (curry next1) alloca start1 create delete
-
-   {-
-   Could be implemented with a machine code loop like in CausalParameterized.
-   But to this end we would need a 'stop' function.
-   -}
-   replicateControlled = CausalClass.replicateControlled
-
-
-toSignal :: T () a -> Sig.T a
-toSignal (Cons next alloca start createIOContext deleteIOContext) = Sig.Cons
-   (\ioContext local -> next ioContext local ())
-   alloca
-   start
-   createIOContext deleteIOContext
-
-fromSignal :: Sig.T b -> T a b
-fromSignal (Sig.Cons next alloca start createIOContext deleteIOContext) = Cons
-   (\ioContext local _ -> next ioContext local)
-   alloca
-   start
-   createIOContext deleteIOContext
-
-
-map ::
-   (C process) =>
-   (forall r. a -> CodeGenFunction r b) ->
-   process a b
-map f =
-   mapAccum (\a s -> fmap (flip (,) s) $ f a) (return ())
-
-mapAccum ::
-   (C process, Memory.C state) =>
-   (forall r.
-    a -> state -> CodeGenFunction r (b, state)) ->
-   (forall r. CodeGenFunction r state) ->
-   process a b
-mapAccum next =
-   simple (\a s -> MaybeCont.lift $ next a s)
-
-zipWith ::
-   (C process) =>
-   (forall r. a -> b -> CodeGenFunction r c) ->
-   process (a,b) c
-zipWith f = map (uncurry f)
-
-
-mapProc ::
-   (C process) =>
-   (forall r. b -> CodeGenFunction r c) ->
-   process a b ->
-   process a c
-mapProc f x = map f <<< x
-
-zipProcWith ::
-   (C process) =>
-   (forall r. b -> c -> CodeGenFunction r d) ->
-   process a b ->
-   process a c ->
-   process a d
-zipProcWith f x y = zipWith f <<< x&&&y
-
-
-takeWhile ::
-   (C process) =>
-   (forall r. a -> CodeGenFunction r (Value Bool)) ->
-   process a a
-takeWhile p =
-   simple
-      (\a () -> do
-         MaybeCont.guard =<< MaybeCont.lift (p a)
-         return (a,()))
-      (return ())
-
-
-compose :: T a b -> T b c -> T a c
-compose
-      (Cons nextA allocaA startA createIOContextA deleteIOContextA)
-      (Cons nextB allocaB startB createIOContextB deleteIOContextB) = Cons
-   (\(paramA, paramB) (localA, localB) a (sa0,sb0) -> do
-      (b,sa1) <- nextA paramA localA a sa0
-      (c,sb1) <- nextB paramB localB b sb0
-      return (c, (sa1,sb1)))
-   (liftM2 (,) allocaA allocaB)
-   (Sig.combineStart startA startB)
-   (Sig.combineCreate createIOContextA createIOContextB)
-   (Sig.combineDelete deleteIOContextA deleteIOContextB)
-
-
-first :: (C process) => process b c -> process (b, d) (c, d)
-first = alter (\(Core next start stop) -> Core (firstNext next) start stop)
-
-
-instance Cat.Category T where
-   id = map return
-   (.) = flip compose
-
-instance Arr.Arrow T where
-   arr f = map (return . f)
-   first = first
-
-
-
-instance Functor (T a) where
-   fmap = ArrowUtil.map
-
-instance Applicative (T a) where
-   pure = ArrowUtil.pure
-   (<*>) = ArrowUtil.apply
-
-
-instance (A.Additive b) => Additive.C (T a b) where
-   zero = pure A.zero
-   negate = mapProc A.neg
-   (+) = zipProcWith A.add
-   (-) = zipProcWith A.sub
-
-instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T a b) where
-   one = pure A.one
-   fromInteger n = pure (A.fromInteger' n)
-   (*) = zipProcWith A.mul
-
-instance (A.Field b, A.RationalConstant b) => Field.C (T a b) where
-   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
-   (/) = zipProcWith A.fdiv
-
-
-instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => P.Num (T a b) where
-   fromInteger n = pure (A.fromInteger' n)
-   negate = mapProc A.neg
-   (+) = zipProcWith A.add
-   (-) = zipProcWith A.sub
-   (*) = zipProcWith A.mul
-   abs = mapProc A.abs
-   signum = mapProc A.signum
-
-instance (A.Field b, A.Real b, A.RationalConstant b) => P.Fractional (T a b) where
-   fromRational x = pure (A.fromRational' x)
-   (/) = zipProcWith A.fdiv
-
-
-
-firstNext ::
-   (Functor m) =>
-   (context -> a -> s -> m (b, s)) ->
-   context -> (a, c) -> s -> m ((b, c), s)
-firstNext next context (b,d) s0 =
-   fmap
-      (\(c,s1) -> ((c,d), s1))
-      (next context b s0)
-
-loopNext ::
-   (Monad m) =>
-   (context -> (a,c) -> state -> m ((b,c), state)) ->
-   context -> a -> (c, state) -> m (b, (c, state))
-loopNext next ctx a0 (c0,s0) = do
-   ((b1,c1), s1) <- next ctx (a0,c0) s0
-   return (b1,(c1,s1))
-
-feedbackControlledAux ::
-   Arrow arrow =>
-   arrow ((ctrl,a),c) b ->
-   arrow (ctrl,b) c ->
-   arrow ((ctrl,a),c) (b,c)
-feedbackControlledAux forth back =
-   arr (fst.fst) &&& forth  >>>  arr snd &&& back
-
-
-reverbParams ::
-   (RandomGen g, Random a) =>
-   g -> Int -> (a, a) -> (Int, Int) -> [(a, Int)]
-reverbParams rnd num gainRange timeRange =
-   flip MS.evalState rnd $
-   replicateM num $
-   liftM2 (,)
-      (MS.state (randomR gainRange))
-      (MS.state (randomR timeRange))
diff --git a/src/Synthesizer/LLVM/Causal/ProcessValue.hs b/src/Synthesizer/LLVM/Causal/ProcessValue.hs
--- a/src/Synthesizer/LLVM/Causal/ProcessValue.hs
+++ b/src/Synthesizer/LLVM/Causal/ProcessValue.hs
@@ -1,50 +1,46 @@
-{- |
-This module provides functions similar to
-"Synthesizer.LLVM.Causal.Process"
-but expects functions that operate on 'Value.T'.
-This way you can use common arithmetic operators
-instead of LLVM assembly functions.
--}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
 module Synthesizer.LLVM.Causal.ProcessValue (
-   map, zipWith, mapAccum, takeWhile,
+   Causal.T,
+   mapAccum,
+   fromModifier,
    ) where
 
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Causal.Private as Causal
 
+import qualified Synthesizer.LLVM.Value as Value
+
+import qualified Synthesizer.Plain.Modifier as Modifier
+
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
 import qualified LLVM.Extra.Memory as Memory
+
 import qualified LLVM.Core as LLVM
 
-import Prelude (Bool)
+import Control.Monad.Trans.State (runState)
 
 
-map ::
-   (Causal.C process) =>
-   (Value.T a -> Value.T b) ->
-   process a b
-map f =
-   Causal.map (Value.unlift1 f)
 
-zipWith ::
-   (Causal.C process) =>
-   (Value.T a -> Value.T b -> Value.T c) ->
-   process (a,b) c
-zipWith f =
-   Causal.zipWith (Value.unlift2 f)
-
 mapAccum ::
-   (Causal.C process, Memory.C s) =>
-   (Value.T a -> Value.T s -> (Value.T b, Value.T s)) ->
-   Value.T s ->
-   process a b
-mapAccum next start =
-   Causal.mapAccum
-      (Value.unlift2 next)
-      (Value.unlift0 start)
+   (Memory.C state) =>
+   (forall r. a -> state -> LLVM.CodeGenFunction r (b, state)) ->
+   (forall r. LLVM.CodeGenFunction r state) ->
+   Causal.T a b
+mapAccum next = Causal.simple (\a s -> MaybeCont.lift $ next a s)
 
-takeWhile ::
-   (Causal.C process) =>
-   (Value.T a -> Value.T (LLVM.Value Bool)) ->
-   process a a
-takeWhile p =
-   Causal.takeWhile (Value.unlift1 p)
+fromModifier ::
+   (Value.Flatten ah, Value.Registers ah ~ al,
+    Value.Flatten bh, Value.Registers bh ~ bl,
+    Value.Flatten ch, Value.Registers ch ~ cl,
+    Value.Flatten sh, Value.Registers sh ~ sl,
+    Memory.C sl) =>
+   Modifier.Simple sh ch ah bh -> Causal.T (cl,al) bl
+fromModifier (Modifier.Simple initial step) =
+   mapAccum
+      (\(c,a) s ->
+         Value.flatten $
+         runState
+            (step (Value.unfold c) (Value.unfold a))
+            (Value.unfold s))
+      (Value.flatten initial)
diff --git a/src/Synthesizer/LLVM/Causal/Render.hs b/src/Synthesizer/LLVM/Causal/Render.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/Render.hs
@@ -0,0 +1,364 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+module Synthesizer.LLVM.Causal.Render where
+
+import qualified Synthesizer.LLVM.Causal.Parameterized as Parameterized
+import Synthesizer.LLVM.Causal.Private (T(Cons))
+import Synthesizer.LLVM.Generator.Render
+         (Triple, tripleStruct,
+          derefStartPtr, derefStopPtr,
+          RunArg, DSLArg, BuildArg(BuildArg), buildArg)
+
+import qualified Synthesizer.LLVM.Plug.Input as PIn
+import qualified Synthesizer.LLVM.Plug.Output as POut
+
+import qualified Synthesizer.CausalIO.Process as PIO
+import qualified Synthesizer.Generic.Cut as Cut
+
+import qualified LLVM.DSL.Execution as Exec
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp(Exp))
+
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Maybe as Maybe
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Data.StorableVector.Base as SVB
+import qualified Data.StorableVector as SV
+
+import Control.Monad (when, join)
+import Control.Applicative (liftA3)
+
+import Foreign.Ptr (Ptr)
+
+import Data.Tuple.HT (snd3)
+import Data.Word (Word)
+
+
+
+foreign import ccall safe "dynamic" derefFillPtr ::
+   Exec.Importer (LLVM.Ptr global -> Word -> Ptr a -> Ptr b -> IO Word)
+
+
+compile ::
+   (Storable.C a, MultiValue.T a ~ al,
+    Storable.C b, MultiValue.T b ~ bl,
+    Marshal.C param, Marshal.Struct param ~ paramStruct) =>
+   (Exp param -> T al bl) ->
+   IO (LLVM.Ptr paramStruct -> Word -> Ptr a -> Ptr b -> IO Word)
+compile proc =
+   Exec.compile "process" $
+   Exec.createFunction derefFillPtr "fill" $ \paramPtr size aPtr bPtr ->
+   case proc (Exp (Memory.load paramPtr)) of
+      Cons next start stop -> do
+         (global,s) <- start
+         local <- LLVM.alloca
+         (pos,_) <- Storable.arrayLoopMaybeCont2 size aPtr bPtr s $
+               \aPtri bPtri s0 -> do
+            a <- MaybeCont.lift $ Storable.load aPtri
+            (b,s1) <- next global local a s0
+            MaybeCont.lift $ Storable.store b bPtri
+            return s1
+         stop global
+         return pos
+
+runAux ::
+   (Marshal.C p,
+    Storable.C a, MultiValue.T a ~ al,
+    Storable.C b, MultiValue.T b ~ bl) =>
+   (Exp p -> T al bl) ->
+   IO (IO () -> p -> SV.Vector a -> IO (SV.Vector b))
+runAux proc = do
+   fill <- compile proc
+   return $ \final param as ->
+      Marshal.with param $ \paramPtr ->
+      SVB.withStartPtr as $ \ aPtr len ->
+      SVB.createAndTrim len $ \bPtr -> do
+         n <- fill paramPtr (fromIntegral len) aPtr bPtr
+         final
+         return $ fromIntegral n
+
+run_ ::
+   (Marshal.C p,
+    Storable.C a, MultiValue.T a ~ al,
+    Storable.C b, MultiValue.T b ~ bl) =>
+   (Exp p -> T al bl) -> IO (p -> SV.Vector a -> IO (SV.Vector b))
+run_ = fmap ($ return ()) . runAux
+
+
+
+foreign import ccall safe "dynamic" derefChunkPtr ::
+   Exec.Importer (LLVM.Ptr globalState -> Word -> Ptr a -> Ptr b -> IO Word)
+
+compileChunky ::
+   (LLVM.IsSized paramStruct, LLVM.Value (LLVM.Ptr paramStruct) ~ pPtr,
+    Memory.C state, Memory.Struct state ~ stateStruct,
+    Memory.C global, Memory.Struct global ~ globalStruct,
+    Triple paramStruct globalStruct stateStruct ~ triple,
+    LLVM.IsSized local,
+    Storable.C a, MultiValue.T a ~ valueA,
+    Storable.C b, MultiValue.T b ~ valueB) =>
+   (forall r z. (Tuple.Phi z) =>
+    pPtr ->
+    global -> LLVM.Value (LLVM.Ptr local) ->
+    valueA -> state -> MaybeCont.T r z (valueB, state)) ->
+   (forall r. pPtr -> LLVM.CodeGenFunction r (global, state)) ->
+   (forall r. pPtr -> global -> LLVM.CodeGenFunction r ()) ->
+   IO (LLVM.Ptr paramStruct -> IO (LLVM.Ptr triple),
+       Exec.Finalizer triple,
+       LLVM.Ptr triple -> Word -> Ptr a -> Ptr b -> IO Word)
+compileChunky next start stop =
+   Exec.compile "process-chunky" $
+   liftA3 (,,)
+      (Exec.createFunction derefStartPtr "startprocess" $
+         \paramPtr -> do
+            paramGlobalStatePtr <- LLVM.malloc
+            (global,state) <- start paramPtr
+            flip LLVM.store paramGlobalStatePtr =<<
+               join
+                  (liftA3 tripleStruct
+                     (LLVM.load paramPtr)
+                     (Memory.compose global)
+                     (Memory.compose state))
+            return paramGlobalStatePtr)
+      (Exec.createFinalizer derefStopPtr "stopprocess" $
+         \paramGlobalStatePtr -> do
+            paramPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d0, ())
+            stop paramPtr =<<
+               Memory.load =<<
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+            LLVM.free paramGlobalStatePtr)
+      (Exec.createFunction derefChunkPtr "fillprocess" $
+         \paramGlobalStatePtr loopLen aPtr bPtr -> do
+            paramPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d0, ())
+            globalPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+            statePtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d2, ())
+            global <- Memory.load globalPtr
+            sInit <- Memory.load statePtr
+            local <- LLVM.alloca
+            (pos,sExit) <-
+               Storable.arrayLoopMaybeCont2 loopLen aPtr bPtr sInit $
+                  \ aPtri bPtri s0 -> do
+               a <- MaybeCont.lift $ Storable.load aPtri
+               (b,s1) <- next paramPtr global local a s0
+               MaybeCont.lift $ Storable.store b bPtri
+               return s1
+            Memory.store (Maybe.fromJust sExit) statePtr
+            return pos)
+
+
+foreign import ccall safe "dynamic" derefChunkPluggedPtr ::
+   Exec.Importer
+      (LLVM.Ptr globalStateStruct -> Word ->
+       LLVM.Ptr inp -> LLVM.Ptr out -> IO Word)
+
+compilePlugged ::
+   (Tuple.Undefined stateIn, Tuple.Phi stateIn) =>
+   (Tuple.Undefined stateOut, Tuple.Phi stateOut) =>
+   (LLVM.IsSized paramStruct, LLVM.Value (LLVM.Ptr paramStruct) ~ pPtr,
+    Memory.C state, Memory.Struct state ~ stateStruct,
+    Memory.C global, Memory.Struct global ~ globalStruct,
+    Triple paramStruct globalStruct stateStruct ~ triple) =>
+   (LLVM.IsSized local) =>
+   (Memory.C paramIn, Memory.Struct paramIn ~ inStruct) =>
+   (Memory.C paramOut, Memory.Struct paramOut ~ outStruct) =>
+   (forall r.
+    paramIn -> stateIn -> LLVM.CodeGenFunction r (valueA, stateIn)) ->
+   (forall r.
+    paramIn -> LLVM.CodeGenFunction r stateIn) ->
+   (forall r z. (Tuple.Phi z) =>
+    pPtr -> global -> LLVM.Value (LLVM.Ptr local) ->
+    valueA -> state -> MaybeCont.T r z (valueB, state)) ->
+   (forall r. pPtr -> LLVM.CodeGenFunction r (global, state)) ->
+   (forall r. pPtr -> global -> LLVM.CodeGenFunction r ()) ->
+   (forall r.
+    paramOut -> valueB -> stateOut -> LLVM.CodeGenFunction r stateOut) ->
+   (forall r.
+    paramOut -> LLVM.CodeGenFunction r stateOut) ->
+   IO (LLVM.Ptr paramStruct -> IO (LLVM.Ptr triple),
+       LLVM.Ptr triple -> IO (),
+       LLVM.Ptr triple ->
+         Word -> LLVM.Ptr inStruct -> LLVM.Ptr outStruct -> IO Word)
+compilePlugged nextIn startIn next start stop nextOut startOut =
+   Exec.compile "process-plugged" $
+   liftA3 (,,)
+      (Exec.createFunction derefStartPtr "startprocess" $
+         \paramPtr -> do
+            paramGlobalStatePtr <- LLVM.malloc
+            (global,state) <- start paramPtr
+            flip LLVM.store paramGlobalStatePtr =<<
+               join
+                  (liftA3 tripleStruct
+                     (LLVM.load paramPtr)
+                     (Memory.compose global)
+                     (Memory.compose state))
+            return paramGlobalStatePtr)
+      (Exec.createFunction derefStopPtr "stopprocess" $
+         \paramGlobalStatePtr -> do
+            paramPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d0, ())
+            stop paramPtr =<<
+               Memory.load =<<
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+            LLVM.free paramGlobalStatePtr)
+      (Exec.createFunction derefChunkPluggedPtr "fillprocess" $
+         \paramGlobalStatePtr loopLen inPtr outPtr -> do
+            paramPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d0, ())
+            globalPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+            statePtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d2, ())
+            global <- Memory.load globalPtr
+            sInit <- Memory.load statePtr
+            inParam  <- Memory.load inPtr
+            outParam <- Memory.load outPtr
+            inInit  <- startIn  inParam
+            outInit <- startOut outParam
+            local <- LLVM.alloca
+            (pos,sExit) <-
+               MaybeCont.fixedLengthLoop loopLen (inInit, sInit, outInit) $
+                  \ (in0,s0,out0) -> do
+               (a,in1) <- MaybeCont.lift $ nextIn inParam in0
+               (b,s1) <- next paramPtr global local a s0
+               out1 <- MaybeCont.lift $ nextOut outParam b out0
+               return (in1, s1, out1)
+            Memory.store (snd3 $ Maybe.fromJust sExit) statePtr
+            return pos)
+
+
+{-
+I liked to write something with signature
+
+> import qualified Synthesizer.Causal.Process as Causal
+>
+> liftStorableChunk ::
+>    (Exp param -> T valueA valueB) ->
+>    IO (param -> Causal.T (SV.Vector a) (SV.Vector b))
+
+but it does not quite work this way.
+@Causal.T@ from @synthesizer-core@ uses an immutable state internally,
+whereas @T@ uses mutable states.
+In principle the immutable state of @Causal.T@
+could be used for breaking the processing of a stream
+and continue it on two different streams in parallel.
+I have no function that makes use of this feature,
+and thus an @ST@ monad might be a way out.
+
+With this function we can convert an LLVM causal process to a causal IO arrow.
+We also need the plugs in order
+to read and write LLVM values from and to Haskell data chunks.
+
+In a second step we could convert this to a processor of lazy lists,
+and thus to a processor of chunky storable vectors.
+-}
+processIOParameterized ::
+   (Marshal.C p, Cut.Read a, x ~ LLVM.Value (LLVM.Ptr (Marshal.Struct p))) =>
+   PIn.T a b -> Parameterized.T x b c -> POut.T c d ->
+   IO (IO (p, IO ()) -> PIO.T a d)
+processIOParameterized
+      (PIn.Cons nextIn startIn createIn deleteIn)
+      paramd
+      (POut.Cons nextOut startOut createOut deleteOut) = do
+   case paramd of
+      Parameterized.Cons next start stop -> do
+         (startFunc, stopFunc, fill) <-
+            compilePlugged
+               nextIn startIn
+               next start stop
+               nextOut startOut
+         return $ \createContext -> PIO.Cons
+            (\a s@(_,statePtr) -> do
+               let maximumSize = Cut.length a
+               (contextIn, paramIn)  <- createIn a
+               (contextOut,paramOut) <- createOut maximumSize
+               actualSize <-
+                  Marshal.with paramIn $ \inptr ->
+                  Marshal.with paramOut $ \outptr ->
+                  fill statePtr (fromIntegral maximumSize) inptr outptr
+               -- print actualSize
+               when (fromIntegral actualSize > maximumSize) $
+                  error $ "CausalParametrized.Process: " ++
+                          "output size " ++ show actualSize ++
+                          " > input size " ++ show maximumSize
+               deleteIn contextIn
+               b <- deleteOut (fromIntegral actualSize) contextOut
+               return (b, s))
+            (do
+               (p, deleteContext) <- createContext
+               ptr <- Marshal.with p startFunc
+               return (deleteContext, ptr))
+            (\(deleteContext, ptr) -> stopFunc ptr >> deleteContext)
+
+processIOCore ::
+   (Marshal.C p, Cut.Read a) =>
+   PIn.T a b -> (Exp p -> T b c) -> POut.T c d ->
+   IO (IO (p, IO ()) -> PIO.T a d)
+processIOCore pin proc pout = do
+   paramd <- Parameterized.fromProcessPtr "Causal.process" proc
+   processIOParameterized pin paramd pout
+
+processIO ::
+   (Marshal.C p, Cut.Read a, PIn.Default a, POut.Default d) =>
+   (Exp p -> T (PIn.Element a) (POut.Element d)) ->
+   IO (p -> PIO.T a d)
+processIO proc =
+   fmap (\f p -> f (return (p, return ()))) $
+   processIOCore PIn.deflt proc POut.deflt
+
+
+class Run f where
+   type DSL f a b
+   type In f
+   type Out f
+   build ::
+      (Marshal.C p) =>
+      PIn.T (In f) a -> (Exp p -> DSL f a b) -> POut.T b (Out f) ->
+      IO (IO (p, IO ()) -> f)
+
+instance (Cut.Read a) => Run (PIO.T a b) where
+   type DSL (PIO.T a b) al bl = T al bl
+   type In (PIO.T a b) = a
+   type Out (PIO.T a b) = b
+   build = processIOCore
+
+instance (RunArg a, Run f) => Run (a -> f) where
+   type DSL (a -> f) al bl = DSLArg a -> DSL f al bl
+   type In (a -> f) = In f
+   type Out (a -> f) = Out f
+   build pin sig pout =
+      case buildArg of
+         BuildArg pass createA -> do
+            f <- build pin (Expr.uncurry $ \p -> sig p . pass) pout
+            return $ \createP av ->
+               f (do (p,finalP) <- createP
+                     (pa,finalA) <- createA av
+                     return ((p,pa), finalA >> finalP))
+
+
+runPlugged :: (Run f) => PIn.T (In f) a -> DSL f a b -> POut.T b (Out f) -> IO f
+runPlugged pin sig pout = do
+   act <- build pin (const sig) pout
+   return $ act (return ((), return ()))
+
+run ::
+   (Run f) =>
+   (In f ~ a, PIn.Default a, PIn.Element a ~ al) =>
+   (Out f ~ b, POut.Default b, POut.Element b ~ bl) =>
+   DSL f al bl -> IO f
+run sig = runPlugged PIn.deflt sig POut.deflt
diff --git a/src/Synthesizer/LLVM/Causal/RingBufferForward.hs b/src/Synthesizer/LLVM/Causal/RingBufferForward.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Causal/RingBufferForward.hs
@@ -0,0 +1,281 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Causal.RingBufferForward (
+   T, track, trackSkip, trackSkipHold,
+   index, mapIndex,
+   ) where
+
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Private as Sig
+import Synthesizer.LLVM.RingBuffer (MemoryPtr)
+
+import Synthesizer.LLVM.Causal.Process (($*#))
+import Synthesizer.Causal.Class (($<), ($*))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Maybe as Maybe
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Control as C
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+import LLVM.Core (CodeGenFunction, Value)
+
+import qualified Control.Arrow as Arrow
+import Control.Arrow ((<<<), (<<^))
+import Data.Tuple.HT (mapSnd, mapPair)
+
+import Data.Word (Word)
+
+import Prelude hiding (length)
+
+
+
+{- |
+This type is very similar to 'Synthesizer.LLVM.RingBuffer.T'
+but differs in several details:
+
+* It stores values in time order,
+  whereas 'Synthesizer.LLVM.RingBuffer.T' stores in opposite order.
+
+* Since it stores future values it is not causal
+  and can only track signal generators.
+
+* There is no need for an initial value.
+
+* It stores one value less than 'Synthesizer.LLVM.RingBuffer.T'
+  since it is meant to provide infixes of the signal
+  rather than providing the basis for a delay line.
+
+Those differences in detail would not justify a new type,
+you could achieve the same by a combination of
+'Synthesizer.LLVM.RingBuffer.track'
+and
+'Synthesizer.LLVM.CausalParameterized.Process.skip'.
+The fundamental problem of this combination is
+that it requires to keep the ring buffer alive
+longer than the providing signal exists.
+This is not possible with the current design.
+That's why we provide the combination of @track@ and @skip@
+in a way that does not suffer from that problem.
+This functionality is critical for
+'Synthesizer.LLVM.CausalParameterized.Helix.dynamic'.
+-}
+data T a =
+   Cons {
+      buffer :: Value (MemoryPtr a),
+      length :: Value Word,
+      current :: Value Word
+   }
+
+{- |
+This function does not check for range violations.
+If the ring buffer was generated by @track time@,
+then the minimum index is zero and the maximum index is @time-1@.
+Index zero refers to the current sample
+and index @time-1@ refers to the one that is farthermost in the future.
+-}
+index :: (Memory.C a) => MultiValue.T Word -> T a -> CodeGenFunction r a
+index (MultiValue.Cons i) rb = do
+   k <- flip A.irem (length rb) =<< A.add (current rb) i
+   Memory.load =<< LLVM.getElementPtr (buffer rb) (k, ())
+
+mapIndex :: (Memory.C a) => Exp Word -> Causal.T (T a) a
+mapIndex k = CausalPriv.map (\buf -> flip index buf =<< Expr.unExp k)
+
+
+{- |
+@track time signal@ bundles @time@ successive values of @signal@.
+The values can be accessed using 'index' with indices
+ranging from 0 to @time-1@.
+
+The @time@ parameter must be non-negative.
+-}
+track :: (Memory.C a) => Exp Word -> Sig.T a -> Sig.T (T a)
+track time input = trackSkip time input $* 1
+
+{- |
+@trackSkip time input $* skips@
+is like
+@Process.skip (track time input) $* skips@
+but this composition would require a @Memory@ constraint for 'T'
+which we cannot provide.
+-}
+trackSkip ::
+   (Memory.C a) =>
+   Exp Word -> Sig.T a -> Causal.T (MultiValue.T Word) (T a)
+trackSkip time (Sig.Cons next start stop) =
+   CausalPriv.Cons
+      (trackNext next)
+      (trackStart start time)
+      (trackStop stop)
+   <<^
+   (\(MultiValue.Cons skip) -> skip)
+
+{- |
+Like @trackSkip@ but repeats the last buffer content
+when the end of the input signal is reached.
+The returned 'Bool' flag is 'True' if a skip could be performed completely
+and it is 'False' if the skip exceeds the end of the input.
+That is, once a 'False' is returned all following values are tagged with 'False'.
+The returned 'Word' value is the number of actually skipped values.
+This lags one step behind the input of skip values.
+The number of an actual number of skips
+is at most the number of requested skips.
+If the flag is 'False', then the number of actual skips is zero.
+The converse does not apply.
+
+If the input signal is too short, the output is undefined.
+(Before the available data the buffer will be filled with arbitrary values.)
+We could fill the buffer with zeros,
+but this would require an Arithmetic constraint
+and the generated signal would not be very meaningful.
+We could also return an empty signal if the input is too short.
+However this would require a permanent check.
+-}
+trackSkipHold ::
+   (Memory.C a) =>
+   Exp Word -> Sig.T a ->
+   Causal.T (MultiValue.T Word) ((MultiValue.T Bool, MultiValue.T Word), T a)
+trackSkipHold time xs =
+   Arrow.first
+      (Arrow.second clearFirst <<^ mapPair (MultiValue.Cons, MultiValue.Cons))
+   <<<
+   trackSkipHold_ time xs
+   <<^
+   (\(MultiValue.Cons skip) -> skip)
+
+clearFirst ::
+   (MultiValue.PseudoRing a, MultiValue.Real a,
+    MultiValue.IntegerConstant a, MultiValue.Select a) =>
+   Causal.MV a a
+clearFirst =
+   Causal.zipWith (\b x -> Expr.select b x 0)
+      $< (Causal.delay1 Expr.false $*# True)
+
+trackSkipHold_ ::
+   (Memory.C a) =>
+   Exp Word -> Sig.T a ->
+   Causal.T (Value Word) ((Value Bool, Value Word), T a)
+trackSkipHold_ time (Sig.Cons next start stop) =
+   CausalPriv.Cons
+      (trackNextHold next)
+      (trackStartHold start time)
+      (trackStopHold stop)
+
+
+trackNext ::
+   (Memory.C al, Tuple.Phi z,
+    Tuple.Phi state, Tuple.Undefined state) =>
+   (forall z0. (Tuple.Phi z0) =>
+    context -> local -> state -> MaybeCont.T r z0 (al, state)) ->
+   (context, (Value Word, Value (MemoryPtr al))) -> local ->
+   Value Word ->
+   (Value Word, (state, Value Word)) ->
+   MaybeCont.T r z (T al, (Value Word, (state, Value Word)))
+trackNext next (context, (size0,ptr)) local n1 (n0, statePos) = do
+   (state3, pos3) <-
+      MaybeCont.fromMaybe $ fmap snd $
+      MaybeCont.fixedLengthLoop n0 statePos $ \(state0, pos0) -> do
+         (a, state1) <- next context local state0
+         MaybeCont.lift $
+            fmap ((,) state1) $ storeNext (size0,ptr) a pos0
+   return (Cons ptr size0 pos3, (n1, (state3, pos3)))
+
+trackStart ::
+   (LLVM.IsSized am, Tuple.Phi state, Tuple.Undefined state) =>
+   CodeGenFunction r (context, state) ->
+   Exp Word ->
+   CodeGenFunction r
+      ((context, (Value Word, Value (LLVM.Ptr am))),
+       (Value Word, (state, Value Word)))
+trackStart start size = do
+   (context, state) <- start
+   ~(MultiValue.Cons size0) <- Expr.unExp size
+   ptr <- LLVM.arrayMalloc size0
+   return ((context, (size0,ptr)), (size0, (state, A.zero)))
+
+trackStop ::
+   (LLVM.IsType am) =>
+   (context -> CodeGenFunction r ()) ->
+   (context, (tl, Value (LLVM.Ptr am))) ->
+   CodeGenFunction r ()
+trackStop stop (context, (_size,ptr)) = do
+   LLVM.free ptr
+   stop context
+
+
+trackNextHold ::
+   (Memory.C al, Tuple.Phi z,
+    Tuple.Phi state, Tuple.Undefined state) =>
+   (forall z0. (Tuple.Phi z0) =>
+    context -> local -> state -> MaybeCont.T r z0 (al, state)) ->
+   (context, (Value Word, Value (MemoryPtr al))) -> local ->
+   Value Word ->
+   (Value Word, (Maybe.T state, Value Word)) ->
+   MaybeCont.T r z
+      (((Value Bool, Value Word), T al),
+       (Value Word, (Maybe.T state, Value Word)))
+trackNextHold next (context, (size0,ptr)) local nNext (n0, (mstate0, pos0)) =
+      MaybeCont.lift $ do
+   (n3, (pos3, state3)) <-
+      Maybe.run mstate0
+         (return (n0, (pos0, mstate0)))
+         (\state0 ->
+            Maybe.loopWithExit (n0, (state0, pos0))
+               (\(n1, (state1, pos1)) -> do
+                  cont <- A.cmp LLVM.CmpGT n1 A.zero
+                  fmap (mapSnd ((,) n1 . (,) pos1)) $
+                     C.ifThen cont
+                        (Maybe.nothing, Maybe.just state1)
+                        (do aState <-
+                              MaybeCont.toMaybe $ next context local state1
+                            return (aState, fmap snd aState)))
+               (\((a,state), (n1, (pos1, _mstate))) -> do
+                  pos2 <- storeNext (size0,ptr) a pos1
+                  n2 <- A.dec n1
+                  return (n2, (state, pos2))))
+   skipped <- A.sub n0 n3
+   return (((Maybe.isJust state3, skipped), Cons ptr size0 pos3),
+           (nNext, (state3, pos3)))
+
+storeNext ::
+   (Memory.C al) =>
+   (Value Word, Value (MemoryPtr al)) ->
+   al -> Value Word -> CodeGenFunction r (Value Word)
+storeNext (size0,ptr) a pos0 = do
+   Memory.store a =<< LLVM.getElementPtr ptr (pos0, ())
+   pos1 <- A.inc pos0
+   cont <- A.cmp LLVM.CmpLT pos1 size0
+   C.select cont pos1 A.zero
+
+
+trackStartHold ::
+   (LLVM.IsSized am,
+    Tuple.Phi state, Tuple.Undefined state) =>
+   CodeGenFunction r (context, state) ->
+   Exp Word ->
+   CodeGenFunction r
+      ((context, (Value Word, Value (LLVM.Ptr am))),
+       (Value Word, (Maybe.T state, Value Word)))
+trackStartHold start size = do
+   (context, state) <- start
+   ~(MultiValue.Cons size0) <- Expr.unExp size
+   ptr <- LLVM.arrayMalloc size0
+   return ((context, (size0,ptr)), (size0, (Maybe.just state, A.zero)))
+
+trackStopHold ::
+   (LLVM.IsType am) =>
+   (context -> CodeGenFunction r ()) ->
+   (context, (Value Word, Value (LLVM.Ptr am))) ->
+   CodeGenFunction r ()
+trackStopHold stop (context, (_size,ptr)) = do
+   LLVM.free ptr
+   stop context
diff --git a/src/Synthesizer/LLVM/CausalParameterized/Controlled.hs b/src/Synthesizer/LLVM/CausalParameterized/Controlled.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/Controlled.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{- |
-This module provides a type class that automatically selects a filter
-for a given parameter type.
-We choose the dependency this way
-because there may be different ways to specify the filter parameters
-but there is only one implementation of the filter itself.
--}
-module Synthesizer.LLVM.CausalParameterized.Controlled (
-   Ctrl.process,
-   processCtrlRate,
-   ) where
-
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Controlled as Ctrl
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.ScalarOrVector as SoV
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (Value, IsFloating)
-
-
-processCtrlRate ::
-   (Ctrl.C parameter a b,
-    Memory.C parameter,
-    Marshal.C r, Tuple.ValueOf r ~ Value r,
-    IsFloating r, SoV.IntegerConstant r,
-    LLVM.CmpRet r, LLVM.IsPrimitive r) =>
-   Param.T p r ->
-   (Param.T p r -> SigP.T p parameter) ->
-   CausalP.T p a b
-processCtrlRate reduct ctrlGen =
-   CausalP.applyFst Ctrl.process
-      (SigP.interpolateConstant reduct (ctrlGen reduct))
diff --git a/src/Synthesizer/LLVM/CausalParameterized/ControlledPacked.hs b/src/Synthesizer/LLVM/CausalParameterized/ControlledPacked.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/ControlledPacked.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{- |
-This is like "Synthesizer.LLVM.CausalParameterized.Controlled"
-but for vectorised signals.
--}
-module Synthesizer.LLVM.CausalParameterized.ControlledPacked (
-   CtrlS.process,
-   processCtrlRate,
-   ) where
-
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.ControlledPacked as CtrlS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.ScalarOrVector as SoV
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (Value, IsFloating)
-
-import qualified Algebra.Field as Field
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base
-import Prelude ()
-
-
-processCtrlRate ::
-   (CtrlS.C parameter av bv,
-    Serial.Read av, n ~ Serial.Size av,
-    Serial.C    bv, n ~ Serial.Size bv,
-    Memory.C parameter,
-    Marshal.C r, Field.C r, IsFloating r, SoV.IntegerConstant r,
-    Tuple.ValueOf r ~ Value r, LLVM.CmpRet r, LLVM.IsPrimitive r) =>
-   Param.T p r ->
-   (Param.T p r -> SigP.T p parameter) ->
-   CausalP.T p av bv
-processCtrlRate reduct ctrlGen = Serial.withSize $ \n ->
-   CausalP.applyFst CtrlS.process
-      (SigP.interpolateConstant
-         (fmap (/ fromIntegral n) reduct)
-         (ctrlGen reduct))
diff --git a/src/Synthesizer/LLVM/CausalParameterized/Functional.hs b/src/Synthesizer/LLVM/CausalParameterized/Functional.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/Functional.hs
+++ /dev/null
@@ -1,531 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.CausalParameterized.Functional (
-   T,
-   lift, fromSignal,
-   ($&), (&|&),
-   compile,
-   compileSignal,
-   withArgs, MakeArguments, Arguments, makeArgs,
-   AnyArg(..),
-
-   Ground(Ground),
-   withGroundArgs, MakeGroundArguments, GroundArguments,
-   makeGroundArgs,
-
-   Atom(..), atom,
-   withGuidedArgs, MakeGuidedArguments, GuidedArguments, PatternArguments,
-   makeGuidedArgs,
-
-   PrepareArguments(PrepareArguments), withPreparedArgs, withPreparedArgs2,
-   atomArg, stereoArgs, pairArgs, tripleArgs,
-   ) where
-
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate as CausalP
-import qualified Synthesizer.LLVM.Causal.ProcessPrivate as Causal
-import qualified Synthesizer.LLVM.Parameterized.Signal as Signal
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.MaybeContinuation as Maybe
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Arithmetic as A
-
-import LLVM.Core (CodeGenFunction)
-import qualified LLVM.Core as LLVM
-
-import qualified Number.Ratio as Ratio
-import qualified Algebra.Transcendental as Trans
-import qualified Algebra.Algebraic as Algebraic
-import qualified Algebra.Field as Field
-import qualified Algebra.Ring as Ring
-import qualified Algebra.Additive as Additive
-
-import qualified Control.Monad.Trans.State as State
-import qualified Control.Monad.Trans.Class as Trans
-import Control.Monad.Trans.State (StateT)
-
-import qualified Data.Vault.Lazy as Vault
-import Data.Vault.Lazy (Vault)
-import qualified Control.Category as Cat
-import Control.Arrow (Arrow, (>>^), (&&&), arr, first)
-import Control.Category (Category, (.))
-import Control.Applicative (Applicative, (<*>), pure, liftA2)
-
-import Data.Tuple.HT (fst3, snd3, thd3)
-
-import qualified System.Unsafe as Unsafe
-
-import Prelude hiding ((.))
-
-
-newtype T p inp out = Cons (Code p inp out)
-
-
--- | similar to @CausalP.T p a b@
-data Code p a b =
-   forall context local state ioContext parameters.
-      (Marshal.C parameters,
-       Memory.C context,
-       Memory.C state) =>
-   Code
-      (forall r c.
-       (Tuple.Phi c) =>
-       context -> local -> a -> state ->
-       StateT Vault (Maybe.T r c) (b, state))
-          -- compute next value
-      (forall r.
-       CodeGenFunction r local)
-          -- allocate temporary variables before a loop
-      (forall r.
-       Tuple.ValueOf parameters ->
-       CodeGenFunction r (context, state))
-          -- initial state
-      (forall r.
-       context -> state ->
-       CodeGenFunction r ())
-          -- cleanup
-      (p -> IO (ioContext, parameters))
-          {- initialization from IO monad
-          This will be run within Unsafe.performIO,
-          so no observable In/Out actions please!
-          -}
-      (ioContext -> IO ())
-          -- finalization from IO monad, also run within Unsafe.performIO
-
-
-
-instance Category (Code p) where
-   id = arr id
-   Code nextB allocaB startB stopB createIOContextB deleteIOContextB .
-      Code nextA allocaA startA stopA createIOContextA deleteIOContextA = Code
-         (CausalP.composeNext
-             (State.mapStateT . Maybe.onFail)
-             stopA stopB nextA nextB)
-         (liftA2 (,) allocaA allocaB)
-         (CausalP.composeStart startA startB)
-         (CausalP.composeStop stopA stopB)
-         (CausalP.composeCreate createIOContextA createIOContextB)
-         (CausalP.composeDelete deleteIOContextA deleteIOContextB)
-
-
-instance Arrow (Code p) where
-   arr f = Code
-      (\ _p () a () -> return (f a, ()))
-      (return ())
-      (\() -> return ((),()))
-      (\() () -> return ())
-      (const $ return ((),()))
-      (const $ return ())
-   first (Code next alloca start stop create delete) = Code
-      (curry $ Causal.firstNext $ uncurry next) alloca start stop
-      create delete
-
-
-{-
-We must not define Category and Arrow instances
-because in osci***osci the result of osci would be shared,
-although it depends on the particular input.
-
-instance Category (T p) where
-   id = tagUnique Cat.id
-   Cons a . Cons b = tagUnique (a . b)
-
-instance Arrow (T p) where
-   arr f = tagUnique $ arr f
-   first (Cons a) = tagUnique $ first a
--}
-
-instance Functor (T p inp) where
-   fmap f (Cons x) =
-      tagUnique $ x >>^ f
-
-instance Applicative (T p inp) where
-   pure a = tagUnique $ arr (const a)
-   f <*> x = fmap (uncurry ($))  $  f &|& x
-
-
-lift0 :: (forall r. CodeGenFunction r out) -> T p inp out
-lift0 f = lift (CausalP.mapSimple (const f))
-
-lift1 :: (forall r. a -> CodeGenFunction r out) -> T p inp a -> T p inp out
-lift1 f x = CausalP.mapSimple f $& x
-
-lift2 :: (forall r. a -> b -> CodeGenFunction r out) -> T p inp a -> T p inp b -> T p inp out
-lift2 f x y = CausalP.zipWithSimple f $& x&|&y
-
-
-instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => Num (T p a b) where
-   fromInteger n = pure (A.fromInteger' n)
-   (+) = lift2 A.add
-   (-) = lift2 A.sub
-   (*) = lift2 A.mul
-   abs = lift1 A.abs
-   signum = lift1 A.signum
-
-instance (A.Field b, A.Real b, A.RationalConstant b) => Fractional (T p a b) where
-   fromRational x = pure (A.fromRational' x)
-   (/) = lift2 A.fdiv
-
-
-instance (A.Additive b) => Additive.C (T p a b) where
-   zero = pure A.zero
-   (+) = lift2 A.add
-   (-) = lift2 A.sub
-   negate = lift1 A.neg
-
-instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T p a b) where
-   one = pure A.one
-   fromInteger n = pure (A.fromInteger' n)
-   (*) = lift2 A.mul
-
-instance (A.Field b, A.RationalConstant b) => Field.C (T p a b) where
-   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
-   (/) = lift2 A.fdiv
-
-instance (A.Transcendental b, A.RationalConstant b) => Algebraic.C (T p a b) where
-   sqrt = lift1 A.sqrt
-   root n x = lift2 A.pow x (Field.recip $ Ring.fromInteger n)
-   x^/r = lift2 A.pow x (Field.fromRational' r)
-
-instance (A.Transcendental b, A.RationalConstant b) => Trans.C (T p a b) where
-   pi = lift0 A.pi
-   sin = lift1 A.sin
-   cos = lift1 A.cos
-   (**) = lift2 A.pow
-   exp = lift1 A.exp
-   log = lift1 A.log
-
-   asin _ = error "LLVM missing intrinsic: asin"
-   acos _ = error "LLVM missing intrinsic: acos"
-   atan _ = error "LLVM missing intrinsic: atan"
-
-
-infixr 0 $&
-
-($&) :: CausalP.T p b c -> T p a b -> T p a c
-f $& (Cons b) =
-   tagUnique $  liftCode f . b
-
-
-infixr 3 &|&
-
-(&|&) :: T p a b -> T p a c -> T p a (b,c)
-Cons b &|& Cons c =
-   tagUnique $  b &&& c
-
-
-liftCode :: CausalP.T p inp out -> Code p inp out
-liftCode (CausalP.Cons next alloca start stop create delete) =
-   Code
-      (\p l a state -> Trans.lift (next p l a state))
-      alloca start stop create delete
-
-lift :: CausalP.T p inp out -> T p inp out
-lift = tagUnique . liftCode
-
-fromSignal :: Signal.T p out -> T p inp out
-fromSignal = lift . CausalP.fromSignal
-
-tag :: Vault.Key out -> Code p inp out -> T p inp out
-tag key (Code next alloca start stop create delete) =
-   Cons $
-   Code
-      (\p l a s0 -> do
-         mb <- State.gets (Vault.lookup key)
-         case mb of
-            Just b -> return (b,s0)
-            Nothing -> do
-               bs@(b,_) <- next p l a s0
-               State.modify (Vault.insert key b)
-               return bs)
-      alloca start stop create delete
-
--- dummy for debugging
-_tag :: Vault.Key out -> Code p inp out -> T p inp out
-_tag _ = Cons
-
-tagUnique :: Code p inp out -> T p inp out
-tagUnique code =
-   Unsafe.performIO $
-   fmap (flip tag code) Vault.newKey
-
-initialize :: Code p inp out -> CausalP.T p inp out
-initialize (Code next alloca start stop create delete) =
-   CausalP.Cons
-      (\p l a state -> State.evalStateT (next p l a state) Vault.empty)
-      alloca start stop create delete
-
-compile :: T p inp out -> CausalP.T p inp out
-compile (Cons code) = initialize code
-
-compileSignal :: T p () out -> Signal.T p out
-compileSignal f = CausalP.toSignal $ compile f
-
-
-{- |
-Using 'withArgs' you can simplify
-
-> let x = F.lift (arr fst)
->     y = F.lift (arr (fst.snd))
->     z = F.lift (arr (snd.snd))
-> in  F.compile (f x y z)
-
-to
-
-> withArgs $ \(x,(y,z)) -> f x y z
--}
-withArgs ::
-   (MakeArguments inp) =>
-   (Arguments (T p inp) inp -> T p inp out) -> CausalP.T p inp out
-withArgs f = withId $ f . makeArgs
-
-withId :: (T p inp inp -> T p inp out) -> CausalP.T p inp out
-withId f = compile $ f $ lift Cat.id
-
-
-type family Arguments (f :: * -> *) (arg :: *)
-
-class MakeArguments arg where
-   makeArgs :: Functor f => f arg -> Arguments f arg
-
-
-{-
-I have thought about an Arg type, that marks where to stop descending.
-This way we can throw away all of these FlexibleContext instances
-and the user can freely choose the granularity of arguments.
-However this does not work so easily,
-because we would need a functional depedency from, say,
-@(Arg a, Arg b)@ to @(a,b)@.
-This is the opposite direction to the dependency we use currently.
-The 'AnyArg' type provides a solution in this spirit.
--}
-type instance Arguments f (LLVM.Value a) = f (LLVM.Value a)
-instance MakeArguments (LLVM.Value a) where
-   makeArgs = id
-
-{- |
-Consistent with pair instance.
-You may use 'AnyArg' or 'withGuidedArgs'
-to stop descending into the stereo channels.
--}
-type instance Arguments f (Stereo.T a) = Stereo.T (Arguments f a)
-instance (MakeArguments a) => MakeArguments (Stereo.T a) where
-   makeArgs = fmap makeArgs . Stereo.sequence
-
-type instance Arguments f (Serial.T v) = f (Serial.T v)
-instance MakeArguments (Serial.T v) where
-   makeArgs = id
-
-type instance Arguments f () = f ()
-instance MakeArguments () where
-   makeArgs = id
-
-type instance Arguments f (a,b) = (Arguments f a, Arguments f b)
-instance (MakeArguments a, MakeArguments b) =>
-      MakeArguments (a,b) where
-   makeArgs f = (makeArgs $ fmap fst f, makeArgs $ fmap snd f)
-
-type instance Arguments f (a,b,c) = (Arguments f a, Arguments f b, Arguments f c)
-instance (MakeArguments a, MakeArguments b, MakeArguments c) =>
-      MakeArguments (a,b,c) where
-   makeArgs f = (makeArgs $ fmap fst3 f, makeArgs $ fmap snd3 f, makeArgs $ fmap thd3 f)
-
-
-{- |
-You can use this to explicitly stop breaking of composed data types.
-It might be more comfortable to do this using 'withGuidedArgs'.
--}
-newtype AnyArg a = AnyArg {getAnyArg :: a}
-
-type instance Arguments f (AnyArg a) = f a
-instance MakeArguments (AnyArg a) where
-   makeArgs = fmap getAnyArg
-
-
-
-{- |
-This is similar to 'withArgs'
-but it requires to specify the decomposition depth
-using constructors in the arguments.
--}
-withGroundArgs ::
-   (MakeGroundArguments (T p inp) args,
-    GroundArguments args ~ inp) =>
-   (args -> T p inp out) -> CausalP.T p inp out
-withGroundArgs f = withId $ f . makeGroundArgs
-
-
-newtype Ground f a = Ground (f a)
-
-
-type family GroundArguments args
-
-class (Functor f) => MakeGroundArguments f args where
-   makeGroundArgs :: f (GroundArguments args) -> args
-
-
-type instance GroundArguments (Ground f a) = a
-instance (Functor f, f ~ g) => MakeGroundArguments f (Ground g a) where
-   makeGroundArgs = Ground
-
-type instance GroundArguments (Stereo.T a) = Stereo.T (GroundArguments a)
-instance MakeGroundArguments f a => MakeGroundArguments f (Stereo.T a) where
-   makeGroundArgs f =
-      Stereo.cons
-         (makeGroundArgs $ fmap Stereo.left f)
-         (makeGroundArgs $ fmap Stereo.right f)
-
-type instance GroundArguments () = ()
-instance (Functor f) => MakeGroundArguments f () where
-   makeGroundArgs _ = ()
-
-
-type instance
-   GroundArguments (a,b) =
-      (GroundArguments a, GroundArguments b)
-instance
-   (MakeGroundArguments f a, MakeGroundArguments f b) =>
-      MakeGroundArguments f (a,b) where
-   makeGroundArgs f =
-      (makeGroundArgs $ fmap fst f,
-       makeGroundArgs $ fmap snd f)
-
-type instance
-   GroundArguments (a,b,c) =
-      (GroundArguments a, GroundArguments b, GroundArguments c)
-instance
-   (MakeGroundArguments f a, MakeGroundArguments f b, MakeGroundArguments f c) =>
-      MakeGroundArguments f (a,b,c) where
-   makeGroundArgs f =
-      (makeGroundArgs $ fmap fst3 f,
-       makeGroundArgs $ fmap snd3 f,
-       makeGroundArgs $ fmap thd3 f)
-
-
-
-{- |
-This is similar to 'withArgs'
-but it allows to specify the decomposition depth using a pattern.
--}
-withGuidedArgs ::
-   (MakeGuidedArguments pat, PatternArguments pat ~ inp) =>
-   pat ->
-   (GuidedArguments (T p inp) pat -> T p inp out) -> CausalP.T p inp out
-withGuidedArgs p f = withId $ f . makeGuidedArgs p
-
-
-data Atom a = Atom
-
-atom :: Atom a
-atom = Atom
-
-
-type family GuidedArguments (f :: * -> *) pat
-type family PatternArguments pat
-
-class MakeGuidedArguments pat where
-   makeGuidedArgs ::
-      Functor f =>
-      pat -> f (PatternArguments pat) -> GuidedArguments f pat
-
-
-type instance GuidedArguments f (Atom a) = f a
-type instance PatternArguments (Atom a) = a
-instance MakeGuidedArguments (Atom a) where
-   makeGuidedArgs Atom = id
-
-type instance GuidedArguments f (Stereo.T a) = Stereo.T (GuidedArguments f a)
-type instance PatternArguments (Stereo.T a) = Stereo.T (PatternArguments a)
-instance MakeGuidedArguments a => MakeGuidedArguments (Stereo.T a) where
-   makeGuidedArgs pat f =
-      Stereo.cons
-         (makeGuidedArgs (Stereo.left  pat) $ fmap Stereo.left f)
-         (makeGuidedArgs (Stereo.right pat) $ fmap Stereo.right f)
-
-type instance GuidedArguments f () = f ()
-type instance PatternArguments () = ()
-instance MakeGuidedArguments () where
-   makeGuidedArgs () = id
-
-type instance
-   GuidedArguments f (a,b) =
-      (GuidedArguments f a, GuidedArguments f b)
-type instance
-   PatternArguments (a,b) =
-      (PatternArguments a, PatternArguments b)
-instance (MakeGuidedArguments a, MakeGuidedArguments b) =>
-      MakeGuidedArguments (a,b) where
-   makeGuidedArgs (pa,pb) f =
-      (makeGuidedArgs pa $ fmap fst f,
-       makeGuidedArgs pb $ fmap snd f)
-
-type instance
-   GuidedArguments f (a,b,c) =
-      (GuidedArguments f a, GuidedArguments f b, GuidedArguments f c)
-type instance
-   PatternArguments (a,b,c) =
-      (PatternArguments a, PatternArguments b, PatternArguments c)
-instance
-   (MakeGuidedArguments a, MakeGuidedArguments b, MakeGuidedArguments c) =>
-      MakeGuidedArguments (a,b,c) where
-   makeGuidedArgs (pa,pb,pc) f =
-      (makeGuidedArgs pa $ fmap fst3 f,
-       makeGuidedArgs pb $ fmap snd3 f,
-       makeGuidedArgs pc $ fmap thd3 f)
-
-
-
-{- |
-Alternative to withGuidedArgs.
-This way of pattern construction is even Haskell 98.
--}
-withPreparedArgs ::
-   PrepareArguments (T p inp) inp a ->
-   (a -> T p inp out) -> CausalP.T p inp out
-withPreparedArgs (PrepareArguments prepare) f = withId $ f . prepare
-
-withPreparedArgs2 ::
-   PrepareArguments (T p (inp0, inp1)) inp0 a ->
-   PrepareArguments (T p (inp0, inp1)) inp1 b ->
-   (a -> b -> T p (inp0, inp1) out) ->
-   CausalP.T p (inp0, inp1) out
-withPreparedArgs2 prepareA prepareB f =
-   withPreparedArgs (pairArgs prepareA prepareB) (uncurry f)
-
-newtype PrepareArguments f merged separated =
-   PrepareArguments (f merged -> separated)
-
-atomArg :: PrepareArguments f a (f a)
-atomArg = PrepareArguments id
-
-stereoArgs ::
-   (Functor f) =>
-   PrepareArguments f a b ->
-   PrepareArguments f (Stereo.T a) (Stereo.T b)
-stereoArgs (PrepareArguments p) =
-   PrepareArguments $ fmap p . Stereo.sequence
-
-pairArgs ::
-   (Functor f) =>
-   PrepareArguments f a0 b0 ->
-   PrepareArguments f a1 b1 ->
-   PrepareArguments f (a0,a1) (b0,b1)
-pairArgs (PrepareArguments p0) (PrepareArguments p1) =
-   PrepareArguments $ \f -> (p0 $ fmap fst f, p1 $ fmap snd f)
-
-tripleArgs ::
-   (Functor f) =>
-   PrepareArguments f a0 b0 ->
-   PrepareArguments f a1 b1 ->
-   PrepareArguments f a2 b2 ->
-   PrepareArguments f (a0,a1,a2) (b0,b1,b2)
-tripleArgs (PrepareArguments p0) (PrepareArguments p1) (PrepareArguments p2) =
-   PrepareArguments $ \f ->
-      (p0 $ fmap fst3 f, p1 $ fmap snd3 f, p2 $ fmap thd3 f)
diff --git a/src/Synthesizer/LLVM/CausalParameterized/FunctionalPlug.hs b/src/Synthesizer/LLVM/CausalParameterized/FunctionalPlug.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/FunctionalPlug.hs
+++ /dev/null
@@ -1,339 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE FlexibleContexts #-}
-module Synthesizer.LLVM.CausalParameterized.FunctionalPlug (
-   T,
-   ($&), (&|&),
-   run, runPlugOut,
-   fromSignal, plug, askParameter, Input,
-   withArgs, withArgsPlugOut,
-   MakeArguments, Arguments, makeArgs,
-   ) where
-
-import qualified Synthesizer.LLVM.Plug.Input as PIn
-import qualified Synthesizer.LLVM.Plug.Output as POut
-
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as Sig
-
-import qualified Synthesizer.CausalIO.Process as PIO
-import qualified Synthesizer.Generic.Cut as CutG
-import qualified Synthesizer.Zip as Zip
-
-import qualified Data.EventList.Relative.BodyTime as EventListBT
-import qualified Data.StorableVector as SV
-
-import qualified LLVM.Extra.Arithmetic as A
-import LLVM.Core (CodeGenFunction)
-
-import qualified Number.Ratio as Ratio
-import qualified Algebra.Transcendental as Trans
-import qualified Algebra.Algebraic as Algebraic
-import qualified Algebra.Field as Field
-import qualified Algebra.Ring as Ring
-import qualified Algebra.Additive as Additive
-
-import qualified Control.Monad.Trans.Reader as MR
-import qualified Control.Monad.Trans.State as MS
-
-import qualified Data.Set as Set
-import qualified Data.Vault.Lazy as Vault
-import Data.Vault.Lazy (Vault)
-import Data.Unique (Unique, newUnique)
-import Data.Maybe (fromMaybe)
-
-import Control.Arrow ((^<<), (<<^), arr, first, second)
-import Control.Category (id, (.))
-import Control.Applicative (Applicative, (<*>), pure, liftA2, liftA3)
-
-import qualified System.Unsafe as Unsafe
-
-import Prelude hiding (id, (.))
-
-
-{- |
-This data type detects sharing.
--}
-{-
-There are two levels of the use of keys.
-At the top level, in T's State monad,
-we store an object id in order to check,
-whether we have already seen a certain object.
-If we encounter a known object
-then we use the Simple constructor
-and fetch the stored CausalP output
-within the causal process enclosed in Simple.
-This and the causal process in the Plugged constructor
-are the second level.
-These arrows handle a Vault like a state monad
-and insert all values they produce into the Vault.
--}
-newtype T pp pl inp out =
-   Cons (MS.State (Set.Set Unique) (Core pp pl inp out))
-
-{-
-We need to hide the x and y types
-since these types grow when combining Cores,
-and then we could not define numeric instances.
--}
-data Core pp pl inp out =
-   forall x y. CutG.Read x =>
-   Plugged
-      (pp -> inp -> x)
-      (PIn.T x y)
-      (CausalP.T pl (y, Vault) (out, Vault))
-   |
-   {-
-   The Simple constructor is needed for reusing shared CausalP processes
-   and for input without external representation. (a Plug.Input)
-   -}
-   Simple (CausalP.T pl Vault (out, Vault))
-
-
-applyCore ::
-   CausalP.T pl (a, Vault) (b, Vault) ->
-   Core pp pl inp a ->
-   Core pp pl inp b
-applyCore f core =
-   case core of
-      Plugged prep plg process -> Plugged prep plg (f . process)
-      Simple process -> Simple (f . process)
-
-combineCore ::
-   Core pp pl inp a ->
-   Core pp pl inp b ->
-   Core pp pl inp (a,b)
-combineCore (Plugged prepA plugA processA) (Plugged prepB plugB processB) =
-   Plugged
-      (\p -> Zip.arrowFanout (prepA p) (prepB p))
-      (PIn.split plugA plugB)
-      ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB
-       . arr (\((a,v),b) -> (a,(b,v))) .
-       first processA <<^ (\((a,b),v) -> ((a,v),b)))
-combineCore (Simple processA) (Plugged prepB plugB processB) =
-   Plugged prepB plugB
-      ((\(b,(a,v)) -> ((a,b), v)) ^<< second processA . processB)
-combineCore (Plugged prepA plugA processA) (Simple processB) =
-   Plugged prepA plugA
-      ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB . processA)
-combineCore (Simple processA) (Simple processB) =
-   Simple ((\(a,(b,v)) -> ((a,b), v)) ^<< second processB . processA)
-
-
-reuseCore :: Vault.Key out -> Core pp pl inp out
-reuseCore key =
-   Simple $ arr $ \vault ->
-      (fromMaybe (error "key must have been lost") $ Vault.lookup key vault,
-       vault)
-
-
-tag ::
-   Unique -> Vault.Key out ->
-   MS.State (Set.Set Unique) (Core pp pl inp out) ->
-   T pp pl inp out
-tag unique key stateCore = Cons $ do
-   alreadySeen <- MS.gets (Set.member unique)
-   if alreadySeen
-      then return $ reuseCore key
-      else do
-         MS.modify (Set.insert unique)
-         fmap (applyCore (arr $ \(a,v) -> (a, Vault.insert key a v))) stateCore
-
-tagUnique ::
-   MS.State (Set.Set Unique) (Core pp pl inp out) ->
-   T pp pl inp out
-tagUnique core =
-   Unsafe.performIO $
-   liftA3 tag newUnique Vault.newKey (pure core)
-
-
-infixr 0 $&
-
-($&) ::
-   CausalP.T pl a b ->
-   T pp pl inp a ->
-   T pp pl inp b
-f  $&  Cons core =
-   tagUnique $ fmap (applyCore $ first f) core
-
-
-infixr 3 &|&
-
-(&|&) ::
-   T pp pl inp a ->
-   T pp pl inp b ->
-   T pp pl inp (a,b)
-Cons coreA  &|&  Cons coreB =
-   tagUnique $ liftA2 combineCore coreA coreB
-
-
-instance Functor (Core pp pl inp) where
-   fmap f (Simple process) = Simple (fmap (first f) process)
-   fmap f (Plugged prep plg process) = Plugged prep plg (fmap (first f) process)
-
-instance Applicative (Core pp pl inp) where
-   pure a = lift0Core $ pure a
-   f <*> x = fmap (uncurry ($))  $  combineCore f x
-
-lift0Core :: (forall r. CodeGenFunction r out) -> Core pp pl inp out
-lift0Core f = Simple (CausalP.mapSimple (\v -> fmap (flip (,) v) f))
-
-
-instance Functor (T pp pl inp) where
-   fmap f (Cons x) = tagUnique $ fmap (fmap f) x
-
-instance Applicative (T pp pl inp) where
-   pure a = tagUnique $ pure $ pure a
-   f <*> x = fmap (uncurry ($))  $  f &|& x
-
-
-lift0 :: (forall r. CodeGenFunction r out) -> T pp pl inp out
-lift0 f = tagUnique $ pure $ lift0Core f
-
-lift1 :: (forall r. a -> CodeGenFunction r out) -> T pp pl inp a -> T pp pl inp out
-lift1 f x = CausalP.mapSimple f $& x
-
-lift2 :: (forall r. a -> b -> CodeGenFunction r out) -> T pp pl inp a -> T pp pl inp b -> T pp pl inp out
-lift2 f x y = CausalP.zipWithSimple f $& x&|&y
-
-
-instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => Num (T pp pl a b) where
-   fromInteger n = pure (A.fromInteger' n)
-   (+) = lift2 A.add
-   (-) = lift2 A.sub
-   (*) = lift2 A.mul
-   abs = lift1 A.abs
-   signum = lift1 A.signum
-
-instance (A.Field b, A.Real b, A.RationalConstant b) => Fractional (T pp pl a b) where
-   fromRational x = pure (A.fromRational' x)
-   (/) = lift2 A.fdiv
-
-
-instance (A.Additive b) => Additive.C (T pp pl a b) where
-   zero = pure A.zero
-   (+) = lift2 A.add
-   (-) = lift2 A.sub
-   negate = lift1 A.neg
-
-instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T pp pl a b) where
-   one = pure A.one
-   fromInteger n = pure (A.fromInteger' n)
-   (*) = lift2 A.mul
-
-instance (A.Field b, A.RationalConstant b) => Field.C (T pp pl a b) where
-   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
-   (/) = lift2 A.fdiv
-
-instance (A.Transcendental b, A.RationalConstant b) => Algebraic.C (T pp pl a b) where
-   sqrt = lift1 A.sqrt
-   root n x = lift2 A.pow x (Field.recip $ Ring.fromInteger n)
-   x^/r = lift2 A.pow x (Field.fromRational' r)
-
-instance (A.Transcendental b, A.RationalConstant b) => Trans.C (T pp pl a b) where
-   pi = lift0 A.pi
-   sin = lift1 A.sin
-   cos = lift1 A.cos
-   (**) = lift2 A.pow
-   exp = lift1 A.exp
-   log = lift1 A.log
-
-   asin _ = error "LLVM missing intrinsic: asin"
-   acos _ = error "LLVM missing intrinsic: acos"
-   atan _ = error "LLVM missing intrinsic: atan"
-
-
-
-fromSignal ::
-   Sig.T pl a ->
-   T pp pl inp a
-fromSignal sig =
-   tagUnique $ pure $ Simple (CausalP.feedFst sig)
-
-
-
-type Input pp a = MR.Reader (pp, a)
-
-plug ::
-   (CutG.Read b, PIn.Default b) =>
-   Input pp a b ->
-   T pp pl a (PIn.Element b)
-plug accessor =
-   tagUnique $ pure $
-   Plugged
-      (curry $ MR.runReader accessor)
-      PIn.deflt
-      id
-
-askParameter :: Input pp a pp
-askParameter = MR.asks fst
-
-
-runPlugOut ::
-   T pp pl a x -> POut.T x b ->
-   IO (pp -> pl -> PIO.T a b)
-runPlugOut (Cons core) pout =
-   case MS.evalState core Set.empty of
-      Plugged prep pin process ->
-         fmap (\f pp pl -> f pl <<^ prep pp) $
-         CausalP.processIOCore
-            pin
-            (fst ^<< process <<^ flip (,) Vault.empty)
-            pout
-      Simple _ ->
-         error "FunctionalPlug.runPlugOut: no substantial input available"
-         -- Simple process ->
-         --    CausalP.processIOCore pin process pout
-
-run ::
-   (POut.Default b) =>
-   T pp pl a (POut.Element b) ->
-   IO (pp -> pl -> PIO.T a b)
-run f = runPlugOut f POut.deflt
-
-
-{- |
-Cf. 'F.withArgs'.
--}
-withArgs ::
-   (MakeArguments a, POut.Default b) =>
-   (Arguments (Input pp a) a -> T pp pl a (POut.Element b)) ->
-   IO (pp -> pl -> PIO.T a b)
-withArgs f = withArgsPlugOut f POut.deflt
-
-withArgsPlugOut ::
-   (MakeArguments a) =>
-   (Arguments (Input pp a) a -> T pp pl a x) ->
-   POut.T x b ->
-   IO (pp -> pl -> PIO.T a b)
-withArgsPlugOut = withArgsPlugOutStart (MR.asks snd)
-
-withArgsPlugOutStart ::
-   (MakeArguments a) =>
-   Input pp a a ->
-   (Arguments (Input pp a) a -> T pp pl a x) ->
-   POut.T x b ->
-   IO (pp -> pl -> PIO.T a b)
-withArgsPlugOutStart fid f = runPlugOut (f (makeArgs fid))
-
-
-
-type family Arguments (f :: * -> *) (arg :: *)
-
-class MakeArguments arg where
-   makeArgs :: Functor f => f arg -> Arguments f arg
-
-
-type instance Arguments f (EventListBT.T i a) = f (EventListBT.T i a)
-instance MakeArguments (EventListBT.T i a) where
-   makeArgs = id
-
-type instance Arguments f (SV.Vector a) = f (SV.Vector a)
-instance MakeArguments (SV.Vector a) where
-   makeArgs = id
-
-type instance Arguments f (Zip.T a b) = (Arguments f a, Arguments f b)
-instance (MakeArguments a, MakeArguments b) =>
-      MakeArguments (Zip.T a b) where
-   makeArgs f = (makeArgs $ fmap Zip.first f, makeArgs $ fmap Zip.second f)
diff --git a/src/Synthesizer/LLVM/CausalParameterized/Helix.hs b/src/Synthesizer/LLVM/CausalParameterized/Helix.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/Helix.hs
+++ /dev/null
@@ -1,636 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE Rank2Types #-}
-{- |
-<http://arxiv.org/abs/0911.5171>
--}
-module Synthesizer.LLVM.CausalParameterized.Helix (
-   -- * time and phase control based on the helix model
-   static,
-   staticPacked,
-   dynamic,
-   dynamicLimited,
-
-   -- * useful control curves
-   zigZag,
-   zigZagPacked,
-   zigZagLong,
-   zigZagLongPacked,
-   ) where
-
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessValue as CausalPV
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate
-                                                              as CausalPrivP
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as Func
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.SignalPrivate as SigP
-import qualified Synthesizer.LLVM.CausalParameterized.RingBufferForward as RingBuffer
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Simple.Value as Value
-import qualified Synthesizer.LLVM.Interpolation as Ip
-import Synthesizer.LLVM.CausalParameterized.Functional (($&), (&|&))
-import Synthesizer.LLVM.CausalParameterized.Process (($*), ($<))
-import Synthesizer.LLVM.Simple.Value ((%>), (%>=), (?), (??))
-
-import qualified Synthesizer.LLVM.Storable.Vector as SVU
-import qualified Data.StorableVector as SV
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value, IsSized, IsFloating)
-
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import Data.Word (Word)
-
-import Foreign.ForeignPtr (touchForeignPtr)
-
-import Control.Arrow (first, (<<<), (^<<), (<<^))
-import Control.Category (id)
-import Control.Applicative (liftA2)
-import Control.Functor.HT (unzip)
-import Data.Traversable (mapM)
-import Data.Tuple.HT (mapFst)
-
-import qualified Algebra.Field as Field
-import qualified Algebra.Ring as Ring
-
-import NumericPrelude.Numeric hiding (splitFraction)
-import NumericPrelude.Base hiding (unzip, zip, mapM, id)
-
-import Prelude ()
-
-
-{- |
-Inputs are @(shape, phase)@.
-
-The shape parameter is limited at the beginning and at the end
-such that only available data is used for interpolation.
-Actually, we allow almost one step less than possible,
-since the right boundary of the interval of admissible @shape@ values is open.
--}
-static ::
-   (Storable.C vh, Tuple.ValueOf vh ~ v,
-    Ip.C nodesStep, Ip.C nodesLeap,
-    SoV.RationalConstant a, SoV.Fraction a,
-    Marshal.C a, Tuple.ValueOf a ~ Value a, LLVM.IsPrimitive a) =>
-   (forall r. Ip.T r nodesLeap (Value a) v) ->
-   (forall r. Ip.T r nodesStep (Value a) v) ->
-   Param.T p Int ->
-   Param.T p a ->
-   Param.T p (SV.Vector vh) ->
-   CausalP.T p (Value a, Value a) v
-static ipLeap ipStep periodInt period vec =
-   let period32 = Param.wordInt periodInt
-       cellMargin = combineMarginParams ipLeap ipStep periodInt
-   in  interpolateCell ipLeap ipStep
-       <<<
-       first (peekCell cellMargin period32 vec)
-       <<<
-       flattenShapePhaseProc period32 period
-       <<<
-       first
-          (limitShape cellMargin period32
-              (Param.wordInt $ fmap SV.length vec))
-
-
-staticPacked ::
-   (Storable.C vh, Tuple.ValueOf vh ~ ve, Serial.Element v ~ ve,
-    Ip.C nodesStep, Ip.C nodesLeap,
-    Serial.Size (nodesLeap (nodesStep v)) ~ n,
-    Serial.C (nodesLeap (nodesStep v)),
-    Serial.Element (nodesLeap (nodesStep v)) ~
-       nodesLeap (nodesStep (Serial.Element v)),
-    TypeNum.Positive n,
-    SoV.RationalConstant a, SoV.Fraction a, Vector.Real a,
-    Marshal.C a, Tuple.ValueOf a ~ Value a, LLVM.IsPrimitive a) =>
-   (forall r. Ip.T r nodesLeap (Serial.Value n a) v) ->
-   (forall r. Ip.T r nodesStep (Serial.Value n a) v) ->
-   Param.T p Int ->
-   Param.T p a ->
-   Param.T p (SV.Vector vh) ->
-   CausalP.T p (Serial.Value n a, Serial.Value n a) v
-staticPacked ipLeap ipStep periodInt period vec =
-   let period32 = Param.wordInt periodInt
-       cellMargin = combineMarginParams ipLeap ipStep periodInt
-   in  interpolateCell ipLeap ipStep
-       <<<
-       first (CausalPS.pack
-          (peekCell (fmap elementMargin cellMargin) period32 vec))
-       <<<
-       flattenShapePhaseProcPacked period32 period
-       <<<
-       first
-          (limitShapePacked cellMargin period32
-              (Param.wordInt $ fmap SV.length vec))
-
-
-{- |
-In contrast to 'dynamic' this one ends
-when the end of the manipulated signal is reached.
--}
-dynamicLimited ::
-   (Ip.C nodesStep, Ip.C nodesLeap,
-    A.Additive v, Memory.C v,
-    SoV.RationalConstant a, SoV.Fraction a,
-    Marshal.C a, Tuple.ValueOf a ~ Value a, LLVM.IsPrimitive a, LLVM.CmpRet a) =>
-   (forall r. Ip.T r nodesLeap (Value a) v) ->
-   (forall r. Ip.T r nodesStep (Value a) v) ->
-   Param.T p Int ->
-   Param.T p a ->
-   SigP.T p v ->
-   CausalP.T p (Value a, Value a) v
-dynamicLimited ipLeap ipStep periodInt period sig =
-   dynamicGen
-      (\cellMargin (skips, fracs) ->
-         let windows =
-                RingBuffer.trackSkip (fmap Ip.marginNumber cellMargin) sig $& skips
-         in  (windows,
-              CausalP.delay1Zero $& skips,
-              CausalP.delay1Zero $& fracs))
-      ipLeap ipStep periodInt period
-
-{- |
-If the time control exceeds the end of the input signal,
-then the last waveform is locked.
-This is analogous to 'static'.
--}
-dynamic ::
-   (Ip.C nodesStep, Ip.C nodesLeap,
-    A.Additive v, Memory.C v,
-    SoV.RationalConstant a, SoV.Fraction a,
-    Marshal.C a, Tuple.ValueOf a ~ Value a, LLVM.IsPrimitive a, LLVM.CmpRet a) =>
-   (forall r. Ip.T r nodesLeap (Value a) v) ->
-   (forall r. Ip.T r nodesStep (Value a) v) ->
-   Param.T p Int ->
-   Param.T p a ->
-   SigP.T p v ->
-   CausalP.T p (Value a, Value a) v
-dynamic ipLeap ipStep periodInt period sig =
-   dynamicGen
-      (\cellMargin (skips, fracs) ->
-         let {-
-             For conformance with 'static'
-             we stop one step before the definite end.
-             We achieve this by using a buffer
-             that is one step longer than necessary.
-             -}
-             ((running, actualSkips), windows) =
-                mapFst unzip $ unzip $
-                RingBuffer.trackSkipHold
-                   (fmap (succ . Ip.marginNumber) cellMargin) sig $& skips
-             holdFracs =
-                CausalPV.zipWithSimple (\r fr -> r ? (fr, 1))
-                $&
-                running &|& (CausalP.delay1Zero $& fracs)
-         in  (windows, actualSkips, holdFracs))
-      ipLeap ipStep periodInt period
-
-dynamicGen ::
-   (Ip.C nodesStep, Ip.C nodesLeap,
-    A.Additive v, Memory.C v,
-    SoV.RationalConstant a, SoV.Fraction a,
-    Marshal.C a, Tuple.ValueOf a ~ Value a, LLVM.IsPrimitive a, LLVM.CmpRet a) =>
-   (Param.T p (Ip.Margin (nodesLeap (nodesStep v))) ->
-    (Func.T p (Value a, Value a) (Value Word),
-     Func.T p (Value a, Value a) (Value a)) ->
-    (Func.T p (Value a, Value a) (RingBuffer.T v),
-     Func.T p (Value a, Value a) (Value Word),
-     Func.T p (Value a, Value a) (Value a))) ->
-   (forall r. Ip.T r nodesLeap (Value a) v) ->
-   (forall r. Ip.T r nodesStep (Value a) v) ->
-   Param.T p Int ->
-   Param.T p a ->
-   CausalP.T p (Value a, Value a) v
-dynamicGen limitMaxShape ipLeap ipStep periodInt period =
-   let period32 = Param.wordInt periodInt
-       cellMargin = combineMarginParams ipLeap ipStep periodInt
-       minShape =
-          Param.wordInt $ fmap fst $
-          liftA2 shapeMargin cellMargin periodInt
-
-   in  Func.withArgs $ \(shape, phase) ->
-          let (windows, skips, fracs) =
-                 limitMaxShape cellMargin $
-                 unzip (integrateFrac $& (limitMinShape minShape $& shape))
-              (offsets, shapePhases) =
-                 unzip
-                    (flattenShapePhaseProc period32 period $&
-                       (constantFromWord32 minShape + fracs)
-                       &|&
-                       (CausalP.osciCoreSync $&
-                          phase
-                          &|&
-                          negate
-                             (CausalPV.map (flip (/)) period $&
-                                (CausalP.mapSimple LLVM.inttofp $& skips))))
-          in  interpolateCell ipLeap ipStep $&
-                 (CausalP.map (uncurry . cellFromBuffer) period32
-                  $&
-                  windows
-                  &|&
-                  offsets)
-                 &|&
-                 shapePhases
-
-constantFromWord32 ::
-   (IsFloating a, LLVM.IsPrimitive a) =>
-   Param.T p Word -> Func.T p inp (Value a)
-constantFromWord32 x =
-   Func.fromSignal
-      (CausalP.mapSimple LLVM.inttofp $* SigP.constant x)
-
-limitMinShape ::
-   (IsFloating a, IsSized a, LLVM.IsPrimitive a, LLVM.CmpRet a) =>
-   Param.T p Word ->
-   CausalP.T p (Value a) (Value a)
-limitMinShape xLim =
-   CausalPV.mapAccum
-      (\_ x lim -> (x%>=lim) ? ((x-lim,zero), (zero,lim-x)))
-      (Value.lift1 LLVM.inttofp) (return ()) xLim
-
-integrateFrac ::
-   (IsFloating a, IsSized a, LLVM.IsPrimitive a) =>
-   CausalP.T p (Value a) (Value Word, Value a)
-integrateFrac =
-   CausalP.mapAccumSimple
-      (\a (_n,frac) -> do
-         s <- splitFraction =<< A.add a frac
-         return (s, s))
-      (return (A.zero, A.zero))
-
-
-interpolateCell ::
-   (Ip.C nodesStep, Ip.C nodesLeap) =>
-   (forall r. Ip.T r nodesLeap a v) ->
-   (forall r. Ip.T r nodesStep a v) ->
-   CausalP.T p (nodesLeap (nodesStep v), (a, a)) v
-interpolateCell ipLeap ipStep =
-   CausalP.mapSimple
-      (\(nodes, (leap,step)) ->
-         ipLeap leap =<< mapM (ipStep step) nodes)
-
-cellFromBuffer ::
-   (Memory.C a, Ip.C nodesLeap, Ip.C nodesStep) =>
-   Value Word ->
-   RingBuffer.T a ->
-   Value Word ->
-   CodeGenFunction r (nodesLeap (nodesStep a))
-cellFromBuffer periodInt buffer offset =
-   Ip.indexNodes
-      (Ip.indexNodes (flip RingBuffer.index buffer) A.one)
-      periodInt offset
-
-elementMargin ::
-   Ip.Margin (nodesLeap (nodesStep v)) ->
-   Ip.Margin (nodesLeap (nodesStep (Serial.Element v)))
-elementMargin (Ip.Margin x y) = Ip.Margin x y
-
-peekCell ::
-   (Storable.C a, Tuple.ValueOf a ~ value, Ip.C nodesLeap, Ip.C nodesStep) =>
-   Param.T p (Ip.Margin (nodesLeap (nodesStep value))) ->
-   Param.T p Word ->
-   Param.T p (SV.Vector a) ->
-   CausalP.T p (Value Word) (nodesLeap (nodesStep value))
-peekCell margin period32 vec =
-   Param.withValue (Param.wordInt $ fmap Ip.marginOffset margin) $ \getOffset valueOffset ->
-   Param.withValue period32 $ \getPeriod valuePeriod -> CausalPrivP.Cons
-      (\(p,off,per) () n () -> MaybeCont.lift $ do
-         offset <- LLVM.bitcast =<< A.sub n (valueOffset off)
-         perInt <- LLVM.bitcast $ valuePeriod per
-         nodes <-
-            Ip.loadNodes (Ip.loadNodes Storable.load A.one) perInt
-               =<< Storable.advancePtr offset p
-         return (nodes, ()))
-      (return ())
-      (return . flip (,) ())
-      (const $ const $ return ())
-      (\p ->
-         let (fp,ptr,_l) = SVU.unsafeToPointers $ Param.get vec p
-         in  return (fp, (ptr, getOffset p, getPeriod p)))
-      touchForeignPtr
-
-
-flattenShapePhaseProc ::
-   (IsFloating a, SoV.Fraction a, SoV.RationalConstant a,
-    Marshal.C ah, Tuple.ValueOf ah ~ Value a, LLVM.IsPrimitive a) =>
-   Param.T p Word ->
-   Param.T p ah ->
-   CausalP.T p
-      (Value a, Value a)
-      (Value Word, (Value a, Value a))
-flattenShapePhaseProc period32 period =
-   CausalP.map
-      (\(perInt, per) (shape, phase) ->
-         flattenShapePhase perInt per shape phase)
-      (liftA2 (,) period32 period)
-
-flattenShapePhaseProcPacked ::
-   (IsFloating a, Vector.Real a, SoV.RationalConstant a,
-    Marshal.C ah, Tuple.ValueOf ah ~ Value a, LLVM.IsPrimitive a,
-    TypeNum.Positive n) =>
-   Param.T p Word ->
-   Param.T p ah ->
-   CausalP.T p
-      (Serial.Value n a, Serial.Value n a)
-      (Serial.Value n Word,
-       (Serial.Value n a, Serial.Value n a))
-flattenShapePhaseProcPacked period32 period =
-   CausalP.map
-      (\(perInt, per) (Serial.Cons shape, Serial.Cons phase) -> do
-         perIntVec <- SoV.replicate perInt
-         perVec <- SoV.replicate per
-         (i, (leap, step)) <-
-            flattenShapePhase perIntVec perVec shape phase
-         return (Serial.Cons i, (Serial.Cons leap, Serial.Cons step)))
-      (liftA2 (,) period32 period)
-
-flattenShapePhase ::
-   (IsFloating a, SoV.Fraction a, SoV.RationalConstant a,
-    LLVM.ShapeOf a ~ LLVM.ShapeOf i, LLVM.IsInteger i) =>
-   Value i ->
-   Value a ->
-   Value a -> Value a ->
-   CodeGenFunction r (Value i, (Value a, Value a))
-flattenShapePhase = Value.unlift4 $ \periodInt period shape phase ->
-   let qLeap = Value.lift1 A.fraction $ shape/period - phase
-       (n,qStep) =
-          unzip $ Value.lift1 splitFraction $
-          {-
-          If 'shape' is correctly limited,
-          the value is always non-negative algebraically,
-          but maybe not numerically.
-          -}
-          Value.max zero $
-          shape - qLeap * Value.lift1 LLVM.inttofp periodInt
-   in  (n,(qLeap,qStep))
-
-{- |
-You must make sure, that the argument is non-negative.
--}
-splitFraction ::
-   (IsFloating a, LLVM.IsInteger i, LLVM.ShapeOf a ~ LLVM.ShapeOf i) =>
-   Value a -> CodeGenFunction r (Value i, Value a)
-splitFraction x = do
-   n <- LLVM.fptoint x
-   frac <- A.sub x =<< LLVM.inttofp n
-   return (n, frac)
-
-
-limitShape ::
-   (IsSized t, IsFloating t, SoV.Real t,
-    LLVM.ShapeOf t ~ LLVM.ShapeOf i,
-    Marshal.C i, Tuple.ValueOf i ~ Value i,
-    Ring.C i, LLVM.IsInteger i, SoV.IntegerConstant i,
-    Ip.C nodesStep, Ip.C nodesLeap) =>
-   Param.T p (Ip.Margin (nodesLeap (nodesStep value))) ->
-   Param.T p i ->
-   Param.T p i ->
-   CausalP.T p (Value t) (Value t)
-limitShape margin periodInt len =
-   CausalPV.zipWithSimple (Value.limit . unzip)
-   $<
-   limitShapeSignal margin periodInt len
-
-limitShapePacked ::
-   (IsSized t, IsFloating t, LLVM.IsPrimitive t, Vector.Real t,
-    TypeNum.Positive n,
-    Ip.C nodesStep, Ip.C nodesLeap) =>
-   Param.T p (Ip.Margin (nodesLeap (nodesStep value))) ->
-   Param.T p Word ->
-   Param.T p Word ->
-   CausalP.T p (Serial.Value n t) (Serial.Value n t)
-limitShapePacked margin periodInt len =
-   CausalPV.zipWithSimple
-      (\minmax shape ->
-         let (minShape,maxShape) = unzip minmax
-         in  Value.limit
-                (Value.lift1 Serial.upsample minShape,
-                 Value.lift1 Serial.upsample maxShape)
-                shape)
-   $<
-   limitShapeSignal margin periodInt len
-
-limitShapeSignal ::
-   (IsSized t, IsFloating t,
-    LLVM.ShapeOf t ~ LLVM.ShapeOf i,
-    Marshal.C i, Tuple.ValueOf i ~ Value i,
-    Ring.C i, LLVM.IsInteger i, SoV.IntegerConstant i,
-    Ip.C nodesStep, Ip.C nodesLeap) =>
-   Param.T p (Ip.Margin (nodesLeap (nodesStep value))) ->
-   Param.T p i ->
-   Param.T p i ->
-   SigP.T p (Value t, Value t)
-limitShapeSignal margin periodInt len =
-   SigP.Cons
-      (\minMax () () -> return (minMax, ()))
-      (return ())
-      (\(minShapeInt, maxShapeInt) -> do
-         minShape <- LLVM.inttofp minShapeInt
-         maxShape <- LLVM.inttofp maxShapeInt
-         return ((minShape, maxShape), ()))
-      (const $ const $ return ())
-      (\p -> return ((),
-         shapeLimits
-            (Param.get margin p)
-            (Param.get periodInt p)
-            (Param.get len p)))
-      (const $ return ())
-
-
-_limitShape ::
-   (Ring.C th, Marshal.C th, Tuple.ValueOf th ~ t, A.Real t,
-    Ip.C nodesStep, Ip.C nodesLeap) =>
-   Ip.Margin (nodesLeap (nodesStep value)) ->
-   Param.T p th ->
-   Param.T p th ->
-   CausalP.T p t t
-_limitShape margin periodInt len =
-   CausalPrivP.Cons
-      (\(minShape,maxShape) () shape () -> MaybeCont.lift $ do
-         limited <- A.min maxShape =<< A.max minShape shape
-         return (limited, ()))
-      (return ())
-      (\minmax -> return (minmax, ()))
-      (const $ const $ return ())
-      (\p ->
-         return
-            ((),
-             shapeLimits margin
-                (Param.get periodInt p)
-                (Param.get len p)))
-      (const $ return ())
-
-shapeLimits ::
-   (Ip.C nodesLeap, Ip.C nodesStep, Ring.C t) =>
-   Ip.Margin (nodesLeap (nodesStep value)) ->
-   t ->
-   t ->
-   (t, t)
-shapeLimits margin periodInt len =
-   case shapeMargin margin periodInt of
-      (leftMargin, rightMargin) ->
-         (leftMargin, len - rightMargin)
-
-_shapeLimits ::
-   (Ip.C nodesLeap, Ip.C nodesStep,
-    IsFloating t, LLVM.ShapeOf t ~ LLVM.ScalarShape) =>
-   Ip.Margin (nodesLeap (nodesStep value)) ->
-   Value.T (Value Word) ->
-   Value.T (Value t) ->
-   (Value.T (Value t), Value.T (Value t))
-_shapeLimits margin periodInt len =
-   let (leftMargin, rightMargin) = shapeMargin margin periodInt
-   in  (Value.lift1 LLVM.inttofp leftMargin,
-        len - Value.lift1 LLVM.inttofp rightMargin)
-
-shapeMargin ::
-   (Ip.C nodesLeap, Ip.C nodesStep, Ring.C i) =>
-   Ip.Margin (nodesLeap (nodesStep value)) ->
-   i -> (i, i)
-shapeMargin margin periodInt =
-   let leftMargin = fromIntegral (Ip.marginOffset margin) + periodInt
-       rightMargin = fromIntegral (Ip.marginNumber margin) - leftMargin
-   in  (leftMargin, rightMargin)
-
-combineMarginParams ::
-   (Ip.C nodesStep, Ip.C nodesLeap) =>
-   (forall r. Ip.T r nodesLeap a v) ->
-   (forall r. Ip.T r nodesStep a v) ->
-   Param.T p Int ->
-   Param.T p (Ip.Margin (nodesLeap (nodesStep v)))
-combineMarginParams ipLeap ipStep periodInt =
-   fmap
-      (combineMargins (Ip.toMargin ipLeap) (Ip.toMargin ipStep))
-      periodInt
-
-combineMargins ::
-   Ip.Margin (nodesLeap value) ->
-   Ip.Margin (nodesStep value) ->
-   Int ->
-   Ip.Margin (nodesLeap (nodesStep value))
-combineMargins marginLeap marginStep periodInt =
-   Ip.Margin {
-      Ip.marginNumber =
-         Ip.marginNumber marginStep +
-         Ip.marginNumber marginLeap * periodInt,
-      Ip.marginOffset =
-         Ip.marginOffset marginStep +
-         Ip.marginOffset marginLeap * periodInt
-   }
-
-
-{- |
-@zigZagLong loopStart loopLength@
-creates a curve that starts at 0
-and is linear until it reaches @loopStart+loopLength@.
-Then it begins looping in a ping-pong manner
-between @loopStart+loopLength@ and @loopStart@.
-It is useful as @shape@ control for looping a sound.
-Input of the causal process is the slope (or frequency) control.
-Slope values must not be negative.
-
-*Main> Sig.renderChunky SVL.defaultChunkSize (Causal.take 25 <<< Helix.zigZagLong 6 10 $* 2) () :: SVL.Vector Float
-VectorLazy.fromChunks [Vector.pack [0.0,1.999999,3.9999995,6.0,8.0,10.0,12.0,14.0,15.999999,14.000001,12.0,10.0,7.999999,6.0,8.0,10.0,12.0,14.0,16.0,14.0,11.999999,9.999998,7.999998,6.0000024,8.000002]]
--}
-zigZagLong ::
-   (Marshal.C a, Tuple.ValueOf a ~ Value a,
-    SoV.Fraction a, IsFloating a, SoV.RationalConstant a, LLVM.CmpRet a,
-    Field.C a) =>
-   Param.T p a ->
-   Param.T p a ->
-   CausalP.T p (Value a) (Value a)
-zigZagLong =
-   zigZagLongGen (CausalP.fromSignal . SigP.constant) zigZag
-
-zigZagLongPacked ::
-   (Marshal.C a, Tuple.ValueOf a ~ Value a,
-    Marshal.Vector n a, Tuple.VectorValueOf n a ~ Value (LLVM.Vector n a),
-    SoV.Fraction a, SoV.RationalConstant a, Vector.Real a,
-    LLVM.IsPrimitive a, Field.C a,
-    (n TypeNum.:*: LLVM.SizeOf a) ~ asize,
-    TypeNum.Positive asize,
-    TypeNum.Positive n) =>
-   Param.T p a ->
-   Param.T p a ->
-   CausalP.T p (Serial.Value n a) (Serial.Value n a)
-zigZagLongPacked =
-   zigZagLongGen (CausalP.fromSignal . SigPS.constant) zigZagPacked
-
-zigZagLongGen ::
-   (A.RationalConstant al, A.Field al, Field.C a) =>
-   (Param.T p a -> CausalP.T p al al) ->
-   (Param.T p a -> CausalP.T p al al) ->
-   Param.T p a ->
-   Param.T p a ->
-   CausalP.T p al al
-zigZagLongGen constant zz prefix loop =
-   zz (negate $ prefix/loop) * constant loop + constant prefix
-   <<<
-   id / constant loop
-
-{- |
-@zigZag start@ creates a zig-zag curve with values between 0 and 1, inclusively,
-that is useful as @shape@ control for looping a sound.
-Input of the causal process is the slope (or frequency) control.
-Slope values must not be negative.
-The start value must be at most 2 and may be negative.
--}
-zigZag ::
-   (Marshal.C a, Tuple.ValueOf a ~ Value a,
-    SoV.Fraction a, IsFloating a, SoV.RationalConstant a, LLVM.CmpRet a) =>
-   Param.T p a ->
-   CausalP.T p (Value a) (Value a)
-zigZag start =
-   CausalPV.mapSimple (\x -> 1-abs (1-x))
-   <<<
-   CausalPV.mapAccum
-      (\_ d t0 ->
-         let t1 = t0+d
-         in  (t0, wrap (curry . (??)) t1))
-      id (return ()) start
-
-zigZagPacked ::
-   (Marshal.C a, Tuple.ValueOf a ~ Value a,
-    SoV.Fraction a, IsFloating a, Vector.Real a, SoV.RationalConstant a,
-    LLVM.CmpRet a,
-    TypeNum.Positive n) =>
-   Param.T p a ->
-   CausalP.T p (Serial.Value n a) (Serial.Value n a)
-zigZagPacked start =
-   Serial.Cons
-   ^<<
-   CausalPV.mapSimple (\x -> 1 - abs (1-x))
-   <<<
-   CausalPV.mapAccum
-      (\_ d t0 ->
-         let (t1, cum) = unzip $ Value.lift2 Vector.cumulate t0 d
-         {-
-         LLVM.select can be replaced by (??)
-         once vector select is implemented by LLVM.
-         -}
-         in  (wrap (Value.lift3 LLVM.select) cum, t1))
-      id (return ()) start
-   <<^
-   (\(Serial.Cons v) -> v)
-
-wrap ::
-   (SoV.RationalConstant a, IsFloating a, SoV.Fraction a, LLVM.CmpRet a) =>
-   (Value.T (Value (LLVM.CmpResult a)) ->
-    Value.T (Value a) ->
-    Value.T (Value a) ->
-    Value.T (Value a)) ->
-   Value.T (Value a) -> Value.T (Value a)
-wrap select a = select (a%>0) (2 * Value.fraction (a/2)) a
diff --git a/src/Synthesizer/LLVM/CausalParameterized/Process.hs b/src/Synthesizer/LLVM/CausalParameterized/Process.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/Process.hs
+++ /dev/null
@@ -1,1044 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-module Synthesizer.LLVM.CausalParameterized.Process (
-   T, simple,
-   fromSignal, toSignal,
-   mapAccum, map, mapSimple, zipWith, zipWithSimple,
-   apply, compose, first,
-   feedFst, feedSnd,
-   loop, loopZero, take, takeWhile, integrate,
-
-   ($<), ($>), ($*),
-   applyFst, applySnd,
-
-   reparameterize,
-
-   mapAccumSimple,
-
-   replicateControlled,
-   replicateParallel,
-   replicateControlledParam,
-   feedbackControlled,
-   Causal.feedbackControlledZero,
-   Causal.fromModifier,
-   fromInitializedModifier,
-   stereoFromMono,
-   stereoFromMonoControlled,
-   stereoFromMonoParameterized,
-   Causal.stereoFromVector,
-   Causal.vectorize,
-   Causal.replaceChannel,
-   Causal.arrayElement,
-   Causal.element,
-   Causal.mix,
-   raise,
-   Causal.envelope,
-   Causal.envelopeStereo,
-   amplify,
-   amplifyStereo,
-   mapLinear,
-   mapExponential,
-   quantizeLift,
-   osciSimple,
-   Causal.osciCore,
-   Causal.osciCoreSync,
-   Causal.shapeModOsci,
-   delay,
-   delayZero,
-   delay1,
-   Causal.delay1Zero,
-   delayControlled,
-   delayControlledInterpolated,
-   differentiate,
-   comb,
-   combStereo,
-   reverbSimple,
-   reverb,
-   Causal.pipeline,
-   Causal.skip,
-   Causal.frequencyModulation,
-   frequencyModulationLinear,
-   trigger,
-
-   runStorable,
-   applyStorable,
-   runStorableChunky,
-   runStorableChunkyCont,
-   applyStorableChunky,
-
-   processIO,
-   processIOCore,
-   ) where
-
-import Synthesizer.LLVM.CausalParameterized.ProcessPrivate
-import Synthesizer.LLVM.Causal.ProcessPrivate
-         (feedbackControlledAux, reverbParams)
-import Synthesizer.LLVM.Causal.Process (loopZero, mix)
-import qualified Synthesizer.LLVM.Causal.ProcessPrivate as CausalPriv
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Plug.Input as PIn
-import qualified Synthesizer.LLVM.Plug.Output as POut
-import qualified Synthesizer.CausalIO.Process as PIO
-
-import qualified Synthesizer.LLVM.CausalParameterized.RingBuffer as RingBuffer
-import qualified Synthesizer.LLVM.Parameterized.SignalPrivate as SigPPriv
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as SigPriv
-import qualified Synthesizer.LLVM.Simple.Value as Value
-import qualified Synthesizer.LLVM.Interpolation as Interpolation
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Frame as Frame
-import qualified Synthesizer.LLVM.ForeignPtr as ForeignPtr
-
-import qualified Synthesizer.Causal.Class as CausalClass
-import qualified Synthesizer.Generic.Cut as Cut
-import qualified Synthesizer.Plain.Modifier as Modifier
-
-import qualified Data.StorableVector.Lazy as SVL
-import qualified Data.StorableVector as SV
-import qualified Data.StorableVector.Base as SVB
-
-import qualified LLVM.DSL.Execution as Exec
-import qualified LLVM.DSL.Parameter as Param
-import LLVM.DSL.Parameter (($#))
-
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Control as C
-import qualified LLVM.Extra.Arithmetic as A
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-          (CodeGenFunction, ret, Value, valueOf,
-           IsSized, IsConst, IsArithmetic, IsFloating)
-
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import qualified Control.Category as Cat
-import Control.Monad.Trans.State (runState)
-import Control.Arrow (arr, first, second, (<<<), (<<^), (>>>), (&&&))
-import Control.Monad (liftM, when)
-import Control.Applicative (liftA2, liftA3, pure, (<*>))
-import Control.Functor.HT (void, unzip)
-import Control.Exception (bracket)
-
-import qualified Data.List as List
-import Data.Traversable (traverse)
-import Data.Foldable (sequence_)
-import Data.Tuple.HT (swap, mapFst, mapSnd, uncurry3, snd3)
-import Data.Word (Word)
-import Data.Int (Int8)
-
-import System.Random (Random, RandomGen)
-
-import Foreign.StablePtr
-          (StablePtr, newStablePtr, freeStablePtr, deRefStablePtr)
-import Foreign.ForeignPtr (touchForeignPtr)
-import Foreign.Ptr (FunPtr, Ptr, freeHaskellFunPtr)
-
-import qualified System.Unsafe as Unsafe
-
-import qualified LLVM.DSL.Debug.Marshal as DebugSt
-import qualified LLVM.DSL.Debug.Counter as DebugCnt
-
-import qualified Algebra.Transcendental as Trans
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base hiding
-          (and, iterate, map, unzip, zip, zipWith, take, takeWhile, sequence_)
-
-
-infixl 0 $<, $>, $*
--- infixr 0 $:*   -- can be used together with $
-
-applyFst, ($<) :: T p (a,b) c -> SigP.T p a -> T p b c
-applyFst = CausalClass.applyFst
-
-applySnd, ($>) :: T p (a,b) c -> SigP.T p b -> T p a c
-applySnd = CausalClass.applySnd
-
-{-
-These infix operators may become methods of a type class
-that can also have synthesizer-core:Causal.Process as instance.
--}
-($*) :: T p a b -> SigP.T p a -> SigP.T p b
-($*) = apply
-($<) = applyFst
-($>) = applySnd
-
-
-reparameterize :: Param.T q p -> T p a b -> T q a b
-reparameterize p (Cons start alloca stop next create delete) =
-   Cons start alloca stop next (create . Param.get p) delete
-
-
-mapAccumSimple ::
-   (Memory.C s) =>
-   (forall r. a -> s -> CodeGenFunction r (b,s)) ->
-   (forall r. CodeGenFunction r s) ->
-   T p a b
-mapAccumSimple f s =
-   mapAccum (\() -> f) (\() -> s) (return ()) (return ())
-
-fromInitializedModifier ::
-   (Value.Flatten ah, Value.Registers ah ~ al,
-    Value.Flatten bh, Value.Registers bh ~ bl,
-    Value.Flatten ch, Value.Registers ch ~ cl,
-    Value.Flatten sh, Value.Registers sh ~ sl, Memory.C sl,
-    Value.Flatten ih, Value.Registers ih ~ il, Memory.C il,
-    Marshal.C i, Tuple.ValueOf i ~ il) =>
-   Modifier.Initialized sh ih ch ah bh -> Param.T p i -> T p (cl,al) bl
-fromInitializedModifier (Modifier.Initialized initF step) =
-   mapAccum
-      (\() (c,a) s ->
-         Value.flatten $
-         runState
-            (step (Value.unfold c) (Value.unfold a))
-            (Value.unfold s))
-      (Value.flattenFunction initF)
-      (return ())
-
-
-replicateParallel ::
-   (Tuple.Undefined b, Tuple.Phi b) =>
-   Param.T p Int -> SigP.T p b -> T p (b,b) b -> T p a b -> T p a b
-replicateParallel n z cum p =
-   replicateControlled n (first p >>> cum) $> z
-
-{-
-There are several problems:
-
- * We have to call f on every parameter in the list,
-   but we have to assume that the generated code is always the same.
-
- * createIOContext may return different types for every element in the list.
-   If types are different, the LLVM code cannot be the same, though.
--}
-replicateControlledParam ::
-   (Tuple.Undefined x, Tuple.Phi x) =>
-   (forall q. Param.T q p -> Param.T q a -> T q (c,x) x) ->
-   Param.T p [a] -> T p (c,x) x
-replicateControlledParam f ps =
-   case f (arr fst) (arr snd) of
-      Cons next alloca start stop createIOContext deleteIOContext -> Cons
-         (replicateControlledNext next stop)
---         (_replicateControlledNext next)
-         alloca
-         (replicateControlledStart start)
-         (replicateControlledStop stop)
-         (\p ->
-            replicateControlledCreate $
-               mapM
-                  (\a -> createIOContext (p,a))
-                  (Param.get ps p))
-         (replicateControlledDelete deleteIOContext)
-
-
--- cf. synthesizer-core:Causal.Process
-feedbackControlled ::
-   (Marshal.C ch, Tuple.ValueOf ch ~ c) =>
-   Param.T p ch ->
-   T p ((ctrl,a),c) b -> T p (ctrl,b) c -> T p (ctrl,a) b
-feedbackControlled initial forth back =
-   loop initial (feedbackControlledAux forth back)
-
-
-{- |
-Run a causal process independently on each stereo channel.
--}
-stereoFromMono ::
-   (Tuple.Phi a, Tuple.Phi b, Tuple.Undefined b) =>
-   T p a b -> T p (Stereo.T a) (Stereo.T b)
-stereoFromMono
-      (Cons next alloca start stop createIOContext deleteIOContext) = Cons
-   (stereoNext stop next)
-   alloca
-   (stereoStart start)
-   (stereoStop stop)
-   (stereoCreate createIOContext createIOContext)
-   (composeDelete deleteIOContext deleteIOContext)
-
-stereoFromMonoControlled ::
-   (Tuple.Phi a, Tuple.Phi b, Tuple.Phi c, Tuple.Undefined b) =>
-   T p (c,a) b -> T p (c, Stereo.T a) (Stereo.T b)
-stereoFromMonoControlled proc =
-   stereoFromMono proc <<^ (\(c,sa) -> fmap ((,) c) sa)
-
-stereoFromMonoParameterized ::
-   (Tuple.Phi a, Tuple.Phi b, Tuple.Undefined b) =>
-   (forall q. Param.T q p -> Param.T q x -> T q a b) ->
-   Param.T p (Stereo.T x) -> T p (Stereo.T a) (Stereo.T b)
-stereoFromMonoParameterized f ps =
-   case f (arr fst) (arr snd) of
-      Cons next alloca start stop createIOContext deleteIOContext -> Cons
-         (stereoNext stop next)
-         alloca
-         (stereoStart start)
-         (stereoStop stop)
-         (stereoCreate
-            (\p -> createIOContext (p, Stereo.left  $ Param.get ps p))
-            (\p -> createIOContext (p, Stereo.right $ Param.get ps p)))
-         (composeDelete deleteIOContext deleteIOContext)
-
-stereoCreate ::
-   Monad m =>
-   (p -> m (ioContextA, context)) ->
-   (p -> m (ioContextB, context)) ->
-   p -> m ((ioContextA, ioContextB), Stereo.T context)
-stereoCreate l r =
-   liftM (mapSnd $ uncurry Stereo.cons) . composeCreate l r
-
-
-stereoNext ::
-   (Tuple.Phi a, Tuple.Phi b, Tuple.Phi c, Tuple.Phi s, Tuple.Phi context,
-    Tuple.Undefined b, Tuple.Undefined s) =>
-   (context -> s -> CodeGenFunction r ()) ->
-   (forall z. (Tuple.Phi z) => context -> local -> a -> s -> MaybeCont.T r z (b, s)) ->
-   Stereo.T context ->
-   local ->
-   Stereo.T a ->
-   Stereo.T s ->
-   MaybeCont.T r c (Stereo.T b, Stereo.T s)
-stereoNext stop next context local a s0 = MaybeCont.fromMaybe $ do
-   mbs1 <-
-      twiceStereo
-         (MaybeCont.toMaybe . uncurry3 (flip next local))
-         (liftA3 (,,) context a s0)
-
-   mbs2 <-
-      if True
-        then Maybe.lift2 Stereo.cons (Stereo.left mbs1) (Stereo.right mbs1)
-        else MaybeCont.toMaybe $ traverse (MaybeCont.fromMaybe . return) mbs1
-
-   end <- Maybe.getIsNothing mbs2
-   C.ifThen end () $
-      sequence_ $
-      liftA2
-         (\mbsi c -> Maybe.for mbsi (stop c . snd))
-         mbs1 context
-
-   return $ fmap unzip mbs2
-
-stereoStart ::
-   (Tuple.Phi a, Tuple.Phi b, Tuple.Phi c, Tuple.Undefined b, Tuple.Undefined c) =>
-   (a -> CodeGenFunction r (c, b)) ->
-   Stereo.T a -> CodeGenFunction r (Stereo.T c, Stereo.T b)
-stereoStart code a =
-   fmap unzip $ twiceStereo code a
-
-stereoStop ::
-   (Tuple.Phi context, Tuple.Phi state) =>
-   (context -> state -> CodeGenFunction r ()) ->
-   Stereo.T context -> Stereo.T state -> CodeGenFunction r ()
-stereoStop code c s = void $ twiceStereo (uncurry code) (liftA2 (,) c s)
-
-twiceStereo ::
-   (Tuple.Phi a, Tuple.Phi b, Tuple.Undefined b) =>
-   (a -> CodeGenFunction r b) ->
-   Stereo.T a -> CodeGenFunction r (Stereo.T b)
-twiceStereo code a =
-   fmap (uncurry Stereo.cons) $
-   twice code (Stereo.left a, Stereo.right a)
-
-twice ::
-   (Tuple.Phi a, Tuple.Phi b, Tuple.Undefined b) =>
-   (a -> CodeGenFunction r b) ->
-   (a,a) -> CodeGenFunction r (b,b)
-twice code a =
-   fmap snd $
-   C.fixedLengthLoop (valueOf (2::Int8)) (a, Tuple.undef) $
-      \((a0,a1), (_,b1)) -> do
-         b0 <- code a0
-         return ((a1,a0), (b1,b0))
-
-
-{- |
-You may also use '(+)' and a 'SigP.constant' signal or a number literal.
--}
-raise ::
-   (A.Additive al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p al al
-raise =
-   map Frame.mix
-
-
-{- |
-You may also use '(*)' and a 'SigP.constant' signal or a number literal.
--}
-amplify ::
-   (A.PseudoRing al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p al al
-amplify =
-   map Frame.amplifyMono
-
-amplifyStereo ::
-   (A.PseudoRing al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p (Stereo.T al) (Stereo.T al)
-amplifyStereo =
-   map Frame.amplifyStereo
-
-
-
-mapLinear ::
-   (IsArithmetic a, Marshal.C a, Tuple.ValueOf a ~ Value a) =>
-   Param.T p a -> Param.T p a -> T p (Value a) (Value a)
-mapLinear depth center =
-   map
-      (\(d,c) x -> A.add c =<< A.mul d x)
-      (depth&&&center)
-
-mapExponential ::
-   (Trans.C a, Marshal.C a, IsFloating a, IsConst a,
-    SoV.TranscendentalConstant a, Tuple.ValueOf a ~ Value a) =>
-   Param.T p a -> Param.T p a -> T p (Value a) (Value a)
-mapExponential depth center =
-   map
-      (\(d,c) x ->
-         A.mul c =<< A.exp =<< A.mul d x)
-      (log depth &&& center)
-
-
-{- |
-@quantizeLift k f@ applies the process @f@ to every @k@th sample
-and repeats the result @k@ times.
-
-Like 'SigP.interpolateConstant' this function can be used
-for computation of filter parameters at a lower rate.
-This can be useful, if you have a frequency control signal at sample rate
-that shall be used both for an oscillator and a frequency filter.
--}
-quantizeLift ::
-   (Memory.C b,
-    Marshal.C c, Tuple.ValueOf c ~ Value cl,
-    SoV.IntegerConstant cl, IsFloating cl,
-    LLVM.CmpRet cl, LLVM.CmpResult cl ~ Bool) =>
-   Param.T p c ->
-   T p a b ->
-   T p a b
-quantizeLift k causal =
-   Causal.quantizeLift causal $< SigP.constant k
-
-
--- for backwards compatibility
-osciSimple ::
-   (SoV.Fraction t, IsSized t) =>
-   (forall r. Value t -> CodeGenFunction r y) ->
-   T p (Value t, Value t) y
-osciSimple = Causal.osci
-
-
-{- |
-Delay time must be non-negative.
-
-The initial value is needed in order to determine the ring buffer element type.
--}
-delay ::
-   (Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> Param.T p Int -> T p al al
-delay initial time =
-   mapSimple RingBuffer.oldest
-   <<<
-   RingBuffer.track initial time
-
-delayZero ::
-   (Memory.C a, A.Additive a) =>
-   Param.T p Int -> T p a a
-delayZero time =
-   mapSimple RingBuffer.oldest
-   <<<
-   RingBuffer.trackConst A.zero time
-
-
-{- |
-Delay by one sample.
-For very small delay times (say up to 8)
-it may be more efficient to apply 'delay1' several times
-or to use a pipeline,
-e.g. @pipeline (id :: T (Vector D4 Float) (Vector D4 Float))@
-delays by 4 samples in an efficient way.
-In principle it would be also possible to use
-@unpack (delay1 (pure $ consVector 0 0 0 0))@
-but 'unpack' causes an additional delay.
-Thus @unpack (id :: T (Vector D4 Float) (Vector D4 Float))@ may do,
-what you want.
--}
-delay1 ::
-   (Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p al al
-delay1 initial = loop initial (arr swap)
-
-
-{- |
-Delay by a variable amount of samples.
-The momentum delay must be between @0@ and @maxTime@, inclusively.
--}
-delayControlled ::
-   (Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> Param.T p Int -> T p (Value Word, al) al
-delayControlled initial maxTime =
-   zipWithSimple RingBuffer.index
-   <<<
-   second (RingBuffer.track initial maxTime)
-
-{- |
-Delay by a variable fractional amount of samples.
-Non-integer delays are achieved by linear interpolation.
-The momentum delay must be between @0@ and @maxTime@, inclusively.
--}
-delayControlledInterpolated ::
-   (Interpolation.C nodes,
-    Marshal.C vh, Tuple.ValueOf vh ~ v,
-    IsFloating a, LLVM.ShapeOf a ~ LLVM.ScalarShape) =>
-   (forall r. Interpolation.T r nodes (Value a) v) ->
-   Param.T p vh -> Param.T p Int -> T p (Value a, v) v
-delayControlledInterpolated ip initial maxTime =
-   let margin = Interpolation.toMargin ip
-   in  zipWithSimple
-          (\del buf -> do
-             let offset =
-                    A.fromInteger' $ fromIntegral $
-                    Interpolation.marginOffset margin
-             n <- A.max offset =<< LLVM.fptoint del
-             k <- A.sub del =<< LLVM.inttofp n
-             m <- A.sub n offset
-             ip k =<<
-                Interpolation.indexNodes (flip RingBuffer.index buf) A.one m)
-       <<<
-       second
-          (RingBuffer.track initial
-              (fmap (Interpolation.marginNumber margin +) maxTime))
-
-
-differentiate ::
-   (A.Additive al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p al al
-differentiate initial =
-   Cat.id - delay1 initial
-
-{- |
-Delay time must be greater than zero!
--}
-comb ::
-   (A.PseudoRing al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> Param.T p Int ->
-   T p al al
-comb gain time =
-   loopZero (mix >>> (Cat.id &&&
-      (delayZero (time-1) >>> amplify gain)))
-
-combStereo ::
-   (A.PseudoRing al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> Param.T p Int ->
-   T p (Stereo.T al) (Stereo.T al)
-combStereo gain time =
-   loopZero (mix >>> (Cat.id &&&
-      (delayZero (time-1) >>> amplifyStereo gain)))
-
-{- |
-Example: apply a stereo reverb to a mono sound.
-
-> traverse
->    (\seed -> reverbSimple (Random.mkStdGen seed) 16 (0.92,0.98) (200,1000))
->    (Stereo.cons 42 23)
-
-There is a serious problem:
-The parameters are not of type 'Param.T',
-thus they cannot depend e.g. on a dynamic sample rate as required by JACK.
--}
-reverbSimple ::
-   (Random a, IsArithmetic a, SoV.RationalConstant a,
-    Marshal.C a, Tuple.ValueOf a ~ Value a,
-    RandomGen g) =>
-   g -> Int -> (a,a) -> (Int,Int) ->
-   T p (Value a) (Value a)
-reverbSimple rnd num gainRange timeRange =
-   mapSimple (A.mul (A.fromRational' $ recip $ fromIntegral num)) <<<
-   (foldl (+) zero $
-    List.map (\(g,t) -> comb $# g $# t) $
-    reverbParams rnd num gainRange timeRange)
-
-reverb ::
-   (Random a, Marshal.C a, Tuple.ValueOf a ~ Value a,
-    SoV.PseudoModule a, SoV.Scalar a ~ s,
-    IsFloating s, SoV.IntegerConstant s, LLVM.IsPrimitive s,
-    RandomGen g) =>
-   Param.T p g -> Param.T p Int -> Param.T p (a,a) -> Param.T p (Int,Int) ->
-   T p (Value a) (Value a)
-reverb rnd num gainRange timeRange =
-   map
-      (\n x -> flip A.scale x =<< A.fdiv A.one =<< LLVM.inttofp n)
-      (Param.wordInt num)
-   <<<
-   replicateControlledParam
-      (\_p p -> first (comb (fmap fst p) (fmap snd p)) >>> mix)
-      (pure reverbParams <*> rnd <*> num <*> gainRange <*> timeRange)
-   <<^
-   (\a -> (a,a))
-
-
-{- |
-Like 'skip' but does not require @Memory@ constraint on the result type.
-This way it can be used on a stream of ring buffer states.
-The downside is that the result is recomputed (from the previous state)
-at every step.
-
-Warning:
-This process is actually unsafe.
-It fails on signal generators that use mutable variables,
-like Signal.storableVectorLazy.
--}
-_skipVolatile ::
-   (Causal.C process, CausalClass.SignalOf process ~ signal) =>
-   signal v -> process (Value Word) v
-_skipVolatile =
-   CausalPriv.alterSignal
-      (\(SigPriv.Core next start stop) -> CausalPriv.Core
-         (\context n state0 -> do
-            y <- fmap fst $ next context state0
-            state1 <-
-               MaybeCont.fromMaybe $ fmap snd $
-               MaybeCont.fixedLengthLoop n state0 $
-               fmap snd . next context
-            return (y, state1))
-         start
-         stop)
-
-
-{- |
-> frequencyModulationLinear signal
-
-is a causal process mapping from a shrinking factor
-to the modulated input @signal@.
-Similar to 'Sig.interpolateConstant'
-but the factor is reciprocal and controllable
-and we use linear interpolation.
-The shrinking factor must be non-negative.
--}
-frequencyModulationLinear ::
-   (SoV.IntegerConstant a, IsFloating a,
-    LLVM.CmpRet a, LLVM.CmpResult a ~ Bool, IsSized a) =>
-   SigP.T p (Value a) -> T p (Value a) (Value a)
-frequencyModulationLinear =
-   Causal.frequencyModulation Interpolation.linear . SigP.adjacentNodes02
-
-
-type Exporter f = f -> IO (FunPtr f)
-
-foreign import ccall safe "wrapper" callbackCreate ::
-   Exporter (LLVM.Ptr lparam -> LLVM.Ptr init -> IO (StablePtr ioContext))
-
-foreign import ccall safe "wrapper" callbackDelete ::
-   Exporter (StablePtr ioContext -> IO ())
-
-stopAndDelete ::
-   LLVM.Function (StablePtr ioContext -> IO ()) ->
-   (context -> state -> CodeGenFunction r ()) ->
-   Maybe.T ((context, state), Value (StablePtr ioContext)) ->
-   CodeGenFunction r ()
-stopAndDelete eraser stop mcsio =
-   Maybe.for mcsio $ \(cs, io) -> do
-      uncurry stop cs
-      void $ LLVM.call eraser io
-
-
-{- |
-@trigger fill signal@ send @signal@ to the output
-and restart it whenever the Boolean process input is 'True'.
-Before the first occurrence of 'True'
-and between instances of the signal the output is filled with 'Maybe.nothing'.
-
-Every restart of the signal needs a call into Haskell code.
-Thus it is certainly a good idea, not to trigger the signal too frequently.
--}
-{-
-Are exceptions handled correctly?
--}
-trigger ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, Tuple.Undefined b, Tuple.Phi b) =>
-   (forall q. Param.T q p -> Param.T q a -> SigP.T q b) ->
-   T p (Maybe.T al) (Maybe.T b)
-trigger sig =
-   triggerAux (sig (arr fst) (arr snd))
-
-triggerAux ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, Tuple.Undefined b, Tuple.Phi b) =>
-   SigP.T (p,a) b ->
-   T p (Maybe.T al) (Maybe.T b)
-triggerAux
-   (SigPPriv.Cons next alloca start stop createIOContext deleteIOContext) = Cons
-   (\(creator, eraser) (local, (param, xPtr)) mx mcsio0 -> MaybeCont.lift $ do
-      mcsio1 <-
-         Maybe.run mx
-            (return mcsio0)
-            (\x ->
-               stopAndDelete eraser stop mcsio0
-               >>
-               do
-                  Memory.store x xPtr
-                  io <- LLVM.call creator param xPtr
-                  cs <- start =<< Memory.load param
-                  return $ Maybe.just (cs, io))
-      mcasio2 <-
-         Maybe.run mcsio1 (return Maybe.nothing) $ \((c1,s1), io1) ->
-            MaybeCont.toMaybe $ fmap (flip (,) io1 . (,) c1) $ next c1 local s1
-      return (fmap (fst.snd.fst) mcasio2, fmap (mapFst (mapSnd snd)) mcasio2))
-   (liftA2 (,) alloca $ liftA2 (,) LLVM.alloca LLVM.alloca)
-   (\ce -> return (ce, Maybe.nothing))
-   (\(_creator, eraser) mcsio -> stopAndDelete eraser stop mcsio)
-   (\p -> do
-      creator <- callbackCreate $ \paramPtr xPtr -> do
-         x <- Marshal.peek xPtr
-         (context, param) <- createIOContext (p,x)
-         Marshal.poke paramPtr param
-         newStablePtr context
-      eraser <- callbackDelete $ \contextPtr -> do
-         deleteIOContext =<< deRefStablePtr contextPtr
-         freeStablePtr contextPtr
-      let ce = (creator, eraser)
-      return (ce, ce))
-   (\(creator, eraser) ->
-      freeHaskellFunPtr creator >>
-      freeHaskellFunPtr eraser)
-
-
-{- |
-On each restart the parameters of type @b@ are passed to the signal.
-
-triggerParam ::
-   (Tuple.Value a, Tuple.ValueOf a ~ al,
-    Tuple.Value b, Tuple.ValueOf b ~ bl) =>
-   Param.T p a ->
-   (Param.T p b -> SigP.T p a) ->
-   T p (Value Bool, bl) al
-triggerParam fill sig =
--}
-
-
-
-foreign import ccall safe "dynamic" derefFillPtr ::
-   Exec.Importer (LLVM.Ptr param -> Word -> Ptr a -> Ptr b -> IO Word)
-
-runStorable ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T p valueA valueB ->
-   IO (p -> SV.Vector a -> SV.Vector b)
-runStorable (Cons next alloca start stop createIOContext deleteIOContext) = do
-   fill <-
-      Exec.compile "process" $
-      Exec.createFunction derefFillPtr "fillprocessblock" $
-      \paramPtr size alPtr blPtr -> do
-         param <- Memory.load paramPtr
-         (c,s) <- start param
-         local <- alloca
-         (pos,msExit) <-
-            Storable.arrayLoopMaybeCont2 size alPtr blPtr s $
-               \ aPtri bPtri s0 -> do
-            a <- MaybeCont.lift $ Storable.load aPtri
-            (b,s1) <- next c local a s0
-            MaybeCont.lift $ Storable.store b bPtri
-            return s1
-         Maybe.for msExit $ stop c
-         ret pos
-
-   return $ \p as ->
-      Unsafe.performIO $
-      bracket (createIOContext p) (deleteIOContext . fst) $
-      \ (_,params) ->
-         SVB.withStartPtr as $ \ aPtr len ->
-         SVB.createAndTrim len $ \ bPtr ->
-         Marshal.with params $ \paramPtr ->
-         fmap fromIntegral $
-            fill paramPtr (fromIntegral len) aPtr bPtr
-
-applyStorable ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T p valueA valueB ->
-   p -> SV.Vector a -> SV.Vector b
-applyStorable gen = Unsafe.performIO $ runStorable gen
-
-
-
-foreign import ccall safe "dynamic" derefChunkPtr ::
-   Exec.Importer
-      (LLVM.Ptr contextStateStruct -> Word -> Ptr a -> Ptr b -> IO Word)
-
-
-compileChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB,
-    Memory.C parameters, Memory.Struct parameters ~ paramStruct,
-    Memory.C context, Memory.C state,
-    Memory.Struct (context, Maybe.T state) ~ contextStateStruct) =>
-   (forall r z.
-    (Tuple.Phi z) =>
-    context -> local ->
-    valueA -> state ->
-    MaybeCont.T r z (valueB, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r.
-    parameters ->
-    CodeGenFunction r (context, state)) ->
-   (forall r.
-    context -> state ->
-    CodeGenFunction r ()) ->
-   IO (LLVM.Ptr paramStruct -> IO (LLVM.Ptr contextStateStruct),
-       Exec.Finalizer contextStateStruct,
-       LLVM.Ptr contextStateStruct -> Word -> Ptr a -> Ptr b -> IO Word)
-compileChunky next alloca start stop =
-   Exec.compile "process-chunky" $
-      liftA3 (,,)
-         (Exec.createFunction derefStartPtr "startprocess" $
-          \paramPtr -> do
-             pptr <- LLVM.malloc
-             flip Memory.store pptr . mapSnd Maybe.just
-                =<< start =<< Memory.load paramPtr
-             ret pptr)
-         (Exec.createFinalizer derefStopPtr "stopprocess" $
-          \ contextStatePtr -> do
-             (c,ms) <- Memory.load contextStatePtr
-             Maybe.for ms $ stop c
-             LLVM.free contextStatePtr
-             ret ())
-         (Exec.createFunction derefChunkPtr "fillprocess" $
-          \ contextStatePtr loopLen aPtr bPtr -> do
-             (param, msInit) <- Memory.load contextStatePtr
-             local <- alloca
-             (pos,msExit) <-
-                Maybe.run msInit (return (A.zero, Maybe.nothing)) $ \sInit ->
-                   Storable.arrayLoopMaybeCont2 loopLen aPtr bPtr sInit $
-                   \ aPtri bPtri s0 -> do
-                a <- MaybeCont.lift $ Storable.load aPtri
-                (b,s1) <- next param local a s0
-                MaybeCont.lift $ Storable.store b bPtri
-                return s1
-             sptr <- LLVM.getElementPtr0 contextStatePtr (TypeNum.d1, ())
-             Memory.store msExit sptr
-             ret pos)
-
-
-foreign import ccall safe "dynamic" derefStartPtr ::
-   Exec.Importer (LLVM.Ptr paramStruct -> IO (LLVM.Ptr contextStateStruct))
-
-foreign import ccall safe "dynamic" derefStopPtr ::
-   Exec.Importer (LLVM.Ptr contextStateStruct -> IO ())
-
-foreign import ccall safe "dynamic" derefChunkPluggedPtr ::
-   Exec.Importer
-      (LLVM.Ptr contextStateStruct -> Word ->
-       LLVM.Ptr inp -> LLVM.Ptr out -> IO Word)
-
-compilePlugged ::
-   (Memory.C parameters, Memory.Struct parameters ~ paramStruct,
-    Memory.C context, Memory.C state,
-    Memory.Struct (context, Maybe.T state) ~ contextStateStruct,
-    Tuple.Undefined stateIn,  Tuple.Phi stateIn,
-    Tuple.Undefined stateOut, Tuple.Phi stateOut,
-    Memory.C paramValueIn,  Memory.Struct paramValueIn  ~ paramStructIn,
-    Memory.C paramValueOut, Memory.Struct paramValueOut ~ paramStructOut) =>
-   (forall r.
-    paramValueIn ->
-    stateIn -> LLVM.CodeGenFunction r (valueA, stateIn)) ->
-   (forall r.
-    paramValueIn ->
-    LLVM.CodeGenFunction r stateIn) ->
-   (forall r z.
-    (Tuple.Phi z) =>
-    context -> local ->
-    valueA -> state ->
-    MaybeCont.T r z (valueB, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r.
-    parameters ->
-    CodeGenFunction r (context, state)) ->
-   (forall r.
-    context -> state ->
-    CodeGenFunction r ()) ->
-   (forall r.
-    paramValueOut ->
-    valueB -> stateOut -> LLVM.CodeGenFunction r stateOut) ->
-   (forall r.
-    paramValueOut ->
-    LLVM.CodeGenFunction r stateOut) ->
-   IO (LLVM.Ptr paramStruct -> IO (LLVM.Ptr contextStateStruct),
-       LLVM.Ptr contextStateStruct -> IO (),
-       LLVM.Ptr contextStateStruct -> Word ->
-         LLVM.Ptr paramStructIn -> LLVM.Ptr paramStructOut -> IO Word)
-compilePlugged nextIn startIn next alloca start stop nextOut startOut =
-   Exec.compile "process-plugged" $
-      liftA3 (,,)
-         (Exec.createFunction derefStartPtr "startprocess" $
-          \paramPtr -> do
-             pptr <- LLVM.malloc
-             flip Memory.store pptr . mapSnd Maybe.just
-                =<< start =<< Memory.load paramPtr
-             ret pptr)
-         (Exec.createFunction derefStopPtr "stopprocess" $
-          \ contextStatePtr -> do
-             (c,ms) <- Memory.load contextStatePtr
-             Maybe.for ms $ stop c
-             LLVM.free contextStatePtr
-             ret ())
-         (Exec.createFunction derefChunkPluggedPtr "fillprocess" $
-          \ contextStatePtr loopLen inPtr outPtr -> do
-             (param, msInit) <- Memory.load contextStatePtr
-             inParam  <- Memory.load inPtr
-             outParam <- Memory.load outPtr
-             inInit  <- startIn  inParam
-             outInit <- startOut outParam
-             local <- alloca
-             (pos,msExit) <-
-                Maybe.run msInit (return (A.zero, Maybe.nothing)) $ \sInit ->
-                   MaybeCont.fixedLengthLoop loopLen (inInit, sInit, outInit) $
-                      \ (in0,s0,out0) -> do
-                (a,in1) <- MaybeCont.lift $ nextIn inParam in0
-                (b,s1) <- next param local a s0
-                out1 <- MaybeCont.lift $ nextOut outParam b out0
-                return (in1, s1, out1)
-             sptr <- LLVM.getElementPtr0 contextStatePtr (TypeNum.d1, ())
-             Memory.store (fmap snd3 msExit) sptr
-             ret pos)
-
-
-runStorableChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T p valueA valueB ->
-   IO (p -> SVL.Vector a -> SVL.Vector b)
-runStorableChunky proc =
-   fmap ($ const SVL.empty) $
-   runStorableChunkyCont proc
-
-{- |
-This function should be used
-instead of @StorableVector.Lazy.Pattern.splitAt@ and subsequent @append@,
-because it does not have the risk of a memory leak.
--}
-runStorableChunkyCont ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T p valueA valueB ->
-   IO ((SVL.Vector a -> SVL.Vector b) ->
-       p -> SVL.Vector a -> SVL.Vector b)
-runStorableChunkyCont
-      (Cons next alloca start stop createIOContext deleteIOContext) = do
-   (startFunc, stopFunc, fill) <- compileChunky next alloca start stop
-   return $
-      \ procRest p sig ->
-      SVL.fromChunks $ Unsafe.performIO $ do
-         (ioContext, param) <- createIOContext p
-
-         when False $
-            DebugCnt.next DebugSt.dumpCounter >>=
-            DebugSt.dump "param" param
-
-         statePtr <- ForeignPtr.newParam stopFunc startFunc param
-         ioContextPtr <- ForeignPtr.newAux (deleteIOContext ioContext)
-
-         let go xt =
-               Unsafe.interleaveIO $
-               case xt of
-                  [] -> return []
-                  x:xs -> SVB.withStartPtr x $ \aPtr size -> do
-                     v <-
-                        ForeignPtr.with statePtr $ \sptr ->
-                        SVB.createAndTrim size $
-                        fmap fromIntegral .
-                        fill sptr (fromIntegral size) aPtr
-                     touchForeignPtr ioContextPtr
-                     (if SV.length v > 0
-                        then fmap (v:)
-                        else id) $
-                        (if SV.length v < size
-                           then return $ SVL.chunks $
-                                procRest $ SVL.fromChunks $
-                                SV.drop (SV.length v) x : xs
-                           else go xs)
-         go (SVL.chunks sig)
-
-applyStorableChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ valueA,
-    Storable.C b, Tuple.ValueOf b ~ valueB) =>
-   T p valueA valueB ->
-   p -> SVL.Vector a -> SVL.Vector b
-applyStorableChunky gen =
-   Unsafe.performIO (runStorableChunky gen)
-
-
-{-
-I liked to write something with signature
-
-> import qualified Synthesizer.Causal.Process as Causal
->
-> liftStorableChunk ::
->    T p valueA valueB ->
->    IO (p -> Causal.T (SV.Vector a) (SV.Vector b))
-
-but it does not quite work this way.
-@Causal.T@ from @synthesizer-core@ uses an immutable state internally,
-whereas @T@ uses mutable states.
-In principle the immutable state of @Causal.T@
-could be used for breaking the processing of a stream
-and continue it on two different streams in parallel.
-I have no function that makes use of this feature,
-and thus an @ST@ monad might be a way out.
-
-With this function we can convert an LLVM causal process to an causal IO arrow.
-We also need the plugs in order
-to read and write LLVM values from and to Haskell data chunks.
-
-In a second step we could convert this to a processor of lazy lists,
-and thus to a processor of chunky storable vectors.
--}
-processIOCore ::
-   (Cut.Read a) =>
-   PIn.T a b ->
-   T p b c ->
-   POut.T c d ->
-   IO (p -> PIO.T a d)
-processIOCore
-      (PIn.Cons nextIn startIn createIn deleteIn)
-      (Cons next alloca start stop createIOContext deleteIOContext)
-      (POut.Cons nextOut startOut createOut deleteOut) = do
-   (startFunc, stopFunc, fill) <-
-      compilePlugged nextIn startIn next alloca start stop nextOut startOut
-   return $ \p -> PIO.Cons
-      (\a s@(_, paramPtr) -> do
-         let maximumSize = Cut.length a
-         (contextIn, paramIn)  <- createIn a
-         (contextOut,paramOut) <- createOut maximumSize
-         actualSize <-
-            Marshal.with paramIn $ \inptr ->
-            Marshal.with paramOut $ \outptr ->
-            fill paramPtr (fromIntegral maximumSize) inptr outptr
-         deleteIn contextIn
-         b <- deleteOut (fromIntegral actualSize) contextOut
-         return (b, s))
-      (do
-         (ioContext, param) <- createIOContext p
-
-         when False $
-            DebugCnt.next DebugSt.dumpCounter >>=
-            DebugSt.dump "param" param
-         contextStatePtr <- Marshal.with param startFunc
-
-         return (ioContext, contextStatePtr))
-      (\(ioContext, contextStatePtr) -> do
-         stopFunc contextStatePtr
-         deleteIOContext ioContext)
-
-processIO ::
-   (Cut.Read a, PIn.Default a, POut.Default d) =>
-   T p (PIn.Element a) (POut.Element d) ->
-   IO (p -> PIO.T a d)
-processIO proc =
-   processIOCore PIn.deflt proc POut.deflt
diff --git a/src/Synthesizer/LLVM/CausalParameterized/ProcessPacked.hs b/src/Synthesizer/LLVM/CausalParameterized/ProcessPacked.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/ProcessPacked.hs
+++ /dev/null
@@ -1,114 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.CausalParameterized.ProcessPacked (
-   CausalS.pack,
-   CausalS.packSmall,
-   CausalS.unpack,
-   raise,
-   amplify,
-   amplifyStereo,
-   CausalS.osciCore,
-   osciSimple,
-   CausalS.shapeModOsci,
-   delay1,
-   differentiate,
-   integrate,
-   CausalS.arrayElement,
-   ) where
-
-import Synthesizer.LLVM.CausalParameterized.ProcessPrivate (T)
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalS
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Frame as Frame
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Arithmetic as A
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value, IsSized, IsArithmetic, IsPrimitive)
-
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import qualified Control.Category as Cat
-
-import Data.Tuple.HT (swap)
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith)
-
-
-raise ::
-   (IsArithmetic a, Marshal.C a, Tuple.ValueOf a ~ Value a, IsPrimitive a,
-    TypeNum.Positive n) =>
-   Param.T p a ->
-   T p (Serial.Value n a) (Serial.Value n a)
-raise =
-   CausalP.map
-      (\x y -> Serial.upsample x >>= flip Frame.mix y)
-
-amplify ::
-   (IsArithmetic a, Marshal.C a, Tuple.ValueOf a ~ Value a, IsPrimitive a,
-    TypeNum.Positive n) =>
-   Param.T p a ->
-   T p (Serial.Value n a) (Serial.Value n a)
-amplify =
-   CausalP.map
-      (\x y -> Serial.upsample x >>= flip Frame.amplifyMono y)
-
-amplifyStereo ::
-   (IsArithmetic a, Marshal.C a, Tuple.ValueOf a ~ Value a, IsPrimitive a,
-    TypeNum.Positive n) =>
-   Param.T p a ->
-   T p (Stereo.T (Serial.Value n a)) (Stereo.T (Serial.Value n a))
-amplifyStereo =
-   CausalP.map
-      (\x y -> Serial.upsample x >>= flip Frame.amplifyStereo y)
-
-
--- for backwards compatibility
-osciSimple ::
-   (Causal.C process,
-    Vector.Real t, SoV.Fraction t, LLVM.IsFloating t, IsSized t,
-    TypeNum.Positive n) =>
-   (forall r. Serial.Value n t -> CodeGenFunction r y) ->
-   process (Serial.Value n t, Serial.Value n t) y
-osciSimple = CausalS.osci
-
-
-delay1 ::
-   (Serial.C va, n ~ Serial.Size va, al ~ Serial.Element va,
-    Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p va va
-delay1 initial =
-   CausalP.loop initial $
-   Causal.map (fmap swap . uncurry Serial.shiftUp . swap)
-
-differentiate ::
-   (Serial.C va, n ~ Serial.Size va, al ~ Serial.Element va,
-    A.Additive va,
-    Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p va va
-differentiate initial =
-   Cat.id - delay1 initial
-
-integrate ::
-   (Vector.Arithmetic a, Marshal.C a, Tuple.ValueOf a ~ Value a, IsPrimitive a,
-    TypeNum.Positive n) =>
-   Param.T p a ->
-   T p (Serial.Value n a) (Serial.Value n a)
-integrate =
-   CausalP.mapAccum
-      (\() a acc0 -> do
-         (acc1,b) <- Serial.cumulate acc0 a
-         return (b,acc1))
-      return
-      (return ())
diff --git a/src/Synthesizer/LLVM/CausalParameterized/ProcessPrivate.hs b/src/Synthesizer/LLVM/CausalParameterized/ProcessPrivate.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/ProcessPrivate.hs
+++ /dev/null
@@ -1,518 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.CausalParameterized.ProcessPrivate where
-
-import qualified Synthesizer.LLVM.Parameterized.SignalPrivate as Sig
-import qualified Synthesizer.LLVM.Causal.ProcessPrivate as CausalPriv
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.ForeignPtr as ForeignPtr
-import Synthesizer.LLVM.Causal.ProcessPrivate (loopNext)
-import Synthesizer.LLVM.Causal.Process (mapProc, zipProcWith)
-import Synthesizer.LLVM.Simple.SignalPrivate (proxyFromElement2)
-
-import qualified Synthesizer.Causal.Class as CausalClass
-import qualified Synthesizer.Causal.Utility as ArrowUtil
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Control as C
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-
-import qualified LLVM.ExecutionEngine as EE
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value, valueOf)
-
-import Type.Data.Num.Decimal (d1)
-
-import qualified Control.Monad.HT as M
-import qualified Control.Arrow    as Arr
-import qualified Control.Category as Cat
-import Control.Arrow (arr, (^<<), (<<<), (&&&))
-import Control.Applicative (Applicative, pure, (<*>), (<$>))
-import Data.Tuple.HT (mapSnd)
-
-import Data.Word (Word)
-
-import Foreign.ForeignPtr (ForeignPtr, touchForeignPtr, mallocForeignPtrBytes)
-
-import qualified System.Unsafe as Unsafe
-
-import qualified Number.Ratio as Ratio
-import qualified Algebra.Field as Field
-import qualified Algebra.Ring as Ring
-import qualified Algebra.Additive as Additive
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith, take, takeWhile, init)
-
-import qualified Prelude as P
-
-
-data T p a b =
-   forall context state local ioContext parameters.
-      (Marshal.C parameters, Memory.C context, Memory.C state) =>
-   Cons
-      (forall r c.
-       (Tuple.Phi c) =>
-       context -> local ->
-       a -> state -> MaybeCont.T r c (b, state))
-          -- compute next value
-      (forall r.
-       CodeGenFunction r local)
-          -- allocate temporary variables before a loop
-      (forall r.
-       Tuple.ValueOf parameters ->
-       CodeGenFunction r (context, state))
-          -- initial state
-      (forall r.
-       context -> state ->
-       CodeGenFunction r ())
-          -- cleanup
-      (p -> IO (ioContext, parameters))
-          {- initialization from IO monad
-          This will be run within Unsafe.performIO,
-          so no observable In/Out actions please!
-          -}
-      (ioContext -> IO ())
-          -- finalization from IO monad, also run within Unsafe.performIO
-
-
-type instance CausalClass.ProcessOf (Sig.T p) = T p
-
-instance CausalClass.C (T p) where
-   type SignalOf (T p) = Sig.T p
-   toSignal = toSignal
-   fromSignal = fromSignal
-
-instance Causal.C (T p) where
-   simple next start =
-      simple (\() -> next) (\() -> fmap ((,) ()) start) (pure ())
-
-   alter f (Cons next0 alloca start0 stop0 create delete) =
-      case f (CausalPriv.Core (uncurry next0) return id) of
-         CausalPriv.Core next1 start1 stop1 ->
-            Cons
-               (curry next1) alloca
-               (Sig.withStart start0 start1)
-               (\c -> stop0 c . stop1)
-               create delete
-
-   replicateControlled n = replicateControlled $ pure n
-
-
-simple ::
-   (Marshal.C parameters, Memory.C context, Memory.C state) =>
-   (forall r c.
-    (Tuple.Phi c) =>
-    context -> a -> state -> MaybeCont.T r c (b, state)) ->
-   (forall r.
-    Tuple.ValueOf parameters ->
-    CodeGenFunction r (context, state)) ->
-   Param.T p parameters -> T p a b
-simple f start param =
-   Param.withValue param $ \get value ->
-   Cons
-      (\context () -> f context)
-      (return ())
-      (start . value)
-      (const $ const $ return ())
-      (return . (,) () . get)
-      (const $ return ())
-
-
-toSignal :: T p () a -> Sig.T p a
-toSignal
-      (Cons next alloca start stop createIOContext deleteIOContext) = Sig.Cons
-   (\p l -> next p l ())
-   alloca
-   start stop
-   createIOContext deleteIOContext
-
-fromSignal :: Sig.T p b -> T p a b
-fromSignal
-      (Sig.Cons next alloca start stop createIOContext deleteIOContext) = Cons
-   (\p l _ -> next p l)
-   alloca
-   start stop
-   createIOContext deleteIOContext
-
-
-mapAccum ::
-   (Marshal.C pnh, Tuple.ValueOf pnh ~ pnl,
-    Marshal.C psh, Tuple.ValueOf psh ~ psl,
-    Memory.C s) =>
-   (forall r. pnl -> a -> s -> CodeGenFunction r (b,s)) ->
-   (forall r. psl -> CodeGenFunction r s) ->
-   Param.T p pnh ->
-   Param.T p psh ->
-   T p a b
-mapAccum next start selectParamN selectParamS =
-   simple
-      (\p a s -> MaybeCont.lift $ next p a s)
-      (\(n,s) -> fmap ((,) n) $ start s)
-      (selectParamN &&& selectParamS)
-
-
-map ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (forall r. pl -> a -> CodeGenFunction r b) ->
-   Param.T p ph ->
-   T p a b
-map f selectParamF =
-   mapAccum
-      (\p a s -> fmap (flip (,) s) $ f p a)
-      (const $ return ())
-      selectParamF
-      (return ())
-
-mapSimple ::
-   (forall r. a -> CodeGenFunction r b) ->
-   T p a b
-mapSimple f =
-   map (const f) (return ())
-
-zipWith ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (forall r. pl -> a -> b -> CodeGenFunction r c) ->
-   Param.T p ph ->
-   T p (a,b) c
-zipWith f =
-   map (uncurry . f)
-
-zipWithSimple ::
-   (forall r. a -> b -> CodeGenFunction r c) ->
-   T p (a,b) c
-zipWithSimple f =
-   mapSimple (uncurry f)
-
-
-apply :: T p a b -> Sig.T p a -> Sig.T p b
-apply = CausalClass.apply
-
-feedFst :: Sig.T p a -> T p b (a,b)
-feedFst = CausalClass.feedFst
-
-feedSnd :: Sig.T p a -> T p b (b,a)
-feedSnd = CausalClass.feedSnd
-
-
-{-
-Very similar to 'apply',
-since 'apply' can be considered being of type
-@T p a b -> T p () a -> T p () b@.
--}
-compose :: T p a b -> T p b c -> T p a c
-compose
-      (Cons nextA allocaA startA stopA createIOContextA deleteIOContextA)
-      (Cons nextB allocaB startB stopB createIOContextB deleteIOContextB) =
-   Cons
-      (composeNext MaybeCont.onFail stopA stopB nextA nextB)
-      (M.lift2 (,) allocaA allocaB)
-      (composeStart startA startB)
-      (composeStop stopA stopB)
-      (composeCreate createIOContextA createIOContextB)
-      (composeDelete deleteIOContextA deleteIOContextB)
-
-composeNext ::
-   (Monad maybe) =>
-   (forall x. code () -> maybe x -> maybe x) ->
-   (contextA -> stateA -> code ()) ->
-   (contextB -> stateB -> code ()) ->
-   (contextA -> localA -> a -> stateA -> maybe (b, stateA)) ->
-   (contextB -> localB -> b -> stateB -> maybe (c, stateB)) ->
-   (contextA, contextB) ->
-   (localA, localB) ->
-   a ->
-   (stateA, stateB) ->
-   maybe (c, (stateA, stateB))
-composeNext onFail stopA stopB nextA nextB
-      (paramA, paramB) (localA, localB) a (sa0,sb0) = do
-   (b,sa1) <- onFail (stopB paramB sb0) $ nextA paramA localA a sa0
-   (c,sb1) <- onFail (stopA paramA sa1) $ nextB paramB localB b sb0
-   return (c, (sa1,sb1))
-
-composeStart ::
-   Monad m =>
-   (paramA -> m (contextA, stateA)) ->
-   (paramB -> m (contextB, stateB)) ->
-   (paramA, paramB) -> m ((contextA, contextB), (stateA, stateB))
-composeStart = Sig.combineStart
-
-composeStop ::
-   Monad m =>
-   (contextA -> stateA -> m ()) ->
-   (contextB -> stateB -> m ()) ->
-   (contextA, contextB) -> (stateA, stateB) -> m ()
-composeStop = Sig.combineStop
-
-composeCreate ::
-   Monad m =>
-   (p -> m (ioContextA, contextA)) ->
-   (p -> m (ioContextB, contextB)) ->
-   p -> m ((ioContextA, ioContextB), (contextA, contextB))
-composeCreate = Sig.combineCreate
-
-composeDelete ::
-   (Monad m) =>
-   (ca -> m ()) -> (cb -> m ()) -> (ca, cb) -> m ()
-composeDelete = Sig.combineDelete
-
-
-{- |
-serial replication
-
-But you may also use it for a parallel replication, see 'replicateParallel'.
--}
-replicateControlled ::
-   (Tuple.Undefined x, Tuple.Phi x) =>
-   Param.T p Int -> T p (c,x) x -> T p (c,x) x
-replicateControlled
-      n (Cons next alloca start stop createIOContext deleteIOContext) =
-   case Param.wordInt n of
-      n32 -> Cons
-         (\(len, cs) ->
-            replicateControlledNext next stop (Param.valueTuple n32 len, cs))
-         (-- we re-use the temporary variable for all stages)
-          alloca)
-         (\(len, param) ->
-            replicateControlledStart start (Param.valueTuple n32 len, param))
-         (\(len, cs) ->
-            replicateControlledStop stop (Param.valueTuple n32 len, cs))
-         (\p ->
-            replicateControlledCreate $
-               M.replicate (Param.get n p) (createIOContext p))
-         (replicateControlledDelete deleteIOContext)
-
-replicateControlledNext ::
-   (Memory.C context, Memory.C state,
-    contextState ~
-       LLVM.Struct (Memory.Struct context, (Memory.Struct state, ())),
-    Tuple.Phi z, Tuple.Phi a, Tuple.Undefined a) =>
-   (forall z0. (Tuple.Phi z0) =>
-    context -> local -> (ctrl, a) -> state ->
-    MaybeCont.T r z0 (a, state)) ->
-   (context -> state -> CodeGenFunction r ()) ->
-   (Value Word, Value (LLVM.Ptr contextState)) ->
-   local ->
-   (ctrl, a) ->
-   () ->
-   MaybeCont.T r z (a, ())
-replicateControlledNext next stop (len, contextStates) local (c,a) () =
-   MaybeCont.fromMaybe $ fmap (\(_,ms) -> flip (,) () <$> ms) $
-      MaybeCont.arrayLoop len contextStates a $
-            \contextStatePtr a0 -> do
-         (context, s0) <- MaybeCont.lift $ Memory.load contextStatePtr
-         (a1,s1) <-
-            MaybeCont.onFail
-               (replicateControlledStopExcept
-                  stop len contextStates contextStatePtr) $
-            next context local (c,a0) s0
-         MaybeCont.lift $
-            Memory.store s1 =<< LLVM.getElementPtr0 contextStatePtr (d1, ())
-         return a1
-
-replicateControlledStopExcept ::
-   (Memory.C a, Memory.C b,
-    ab ~ LLVM.Struct (Memory.Struct a, (Memory.Struct b, ()))) =>
-   (a -> b -> CodeGenFunction r ()) ->
-   Value Word ->
-   Value (LLVM.Ptr ab) ->
-   Value (LLVM.Ptr ab) ->
-   CodeGenFunction r ()
-replicateControlledStopExcept stop len contextStates contextStatePtr =
-   C.arrayLoop len contextStates () $ \ptr () -> do
-      b <- A.cmp LLVM.CmpNE ptr contextStatePtr
-      C.ifThen b () $ uncurry stop =<< Memory.load ptr
-
-_replicateControlledNext ::
-   (Memory.C context, Memory.C state,
-    contextState ~
-       LLVM.Struct (Memory.Struct context, (Memory.Struct state, ())),
-    Tuple.Phi z, Tuple.Phi a, Tuple.Undefined a) =>
-   (forall z0. (Tuple.Phi z0) =>
-    context -> (ctrl, a) -> state ->
-    MaybeCont.T r z0 (a, state)) ->
-   (Value Word, Value (LLVM.Ptr contextState)) ->
-   (ctrl, a) ->
-   () ->
-   MaybeCont.T r z (a, ())
-_replicateControlledNext next (len, contextStates) (c,a) () =
-   fmap (flip (,) ()) $ MaybeCont.fromBool $ fmap snd $
-   C.arrayLoopWithExit len contextStates (valueOf True, a) $
-         \contextStatePtr (_,a0) -> do
-      (context, s0) <- Memory.load contextStatePtr
-      (cont, (a1,s1)) <- MaybeCont.toBool $ next context (c,a0) s0
-      Memory.store s1 =<< LLVM.getElementPtr0 contextStatePtr (d1, ())
-      return (cont, (cont,a1))
-
-replicateControlledStart ::
-   (Memory.C a, Memory.C b) =>
-   (a -> CodeGenFunction r b) ->
-   (Value Word, Value (LLVM.Ptr (Memory.Struct a))) ->
-   CodeGenFunction r ((Value Word, Value (LLVM.Ptr (Memory.Struct b))), ())
-replicateControlledStart start (len, params) = do
-   contextStates <- LLVM.arrayMalloc len
-   C.arrayLoop2 len params contextStates () $ \paramPtr statePtr () ->
-      flip Memory.store statePtr =<< start =<< Memory.load paramPtr
-   return ((len, contextStates), ())
-
-replicateControlledStop ::
-   (Memory.C a, Memory.C b,
-    ab ~ LLVM.Struct (Memory.Struct a, (Memory.Struct b, ()))) =>
-   (a -> b -> CodeGenFunction r ()) ->
-   (Value Word, Value (LLVM.Ptr ab)) ->
-   () ->
-   CodeGenFunction r ()
-replicateControlledStop stop (len, contextStates) () = do
-   C.arrayLoop len contextStates () $ \contextStatePtr () ->
-      uncurry stop =<< Memory.load contextStatePtr
-   LLVM.free contextStates
-
-
-replicateControlledCreate ::
-   (Monad m, Marshal.C b, Marshal.Struct b ~ struct) =>
-   m [(a, b)] ->
-   m (([a], ForeignPtr.MemoryPtr struct), (Word, LLVM.Ptr struct))
-replicateControlledCreate createIOContexts = do
-   (ioContexts, params) <- M.lift unzip createIOContexts
-   let len = length params
-   let fptr = Unsafe.performIO $ do
-         fptr0 <-
-            mallocForeignPtrBytes $ EE.sizeOfArray (proxyFromElement2 fptr) len
-         ForeignPtr.with fptr0 $ flip EE.pokeList (fmap Marshal.pack params)
-         return fptr0
-   return ((ioContexts, fptr),
-           (fromIntegral len,
-            EE.castFromStoredPtr $ Unsafe.foreignPtrToPtr fptr))
-
-replicateControlledDelete ::
-   (a -> IO ()) ->
-   ([a], ForeignPtr b) -> IO ()
-replicateControlledDelete deleteIOContext (ioContexts, fptr) = do
-   mapM_ deleteIOContext ioContexts
-   touchForeignPtr fptr
-
-
-instance Cat.Category (T p) where
-   id = mapSimple return
-   (.) = flip compose
-
-instance Arr.Arrow (T p) where
-   arr f = mapSimple (return . f)
-   first = Causal.first
-
-
-instance Functor (T p a) where
-   fmap = ArrowUtil.map
-
-instance Applicative (T p a) where
-   pure = ArrowUtil.pure
-   (<*>) = ArrowUtil.apply
-
-
-instance (A.Additive b) => Additive.C (T p a b) where
-   zero = pure A.zero
-   negate = mapProc A.neg
-   (+) = zipProcWith A.add
-   (-) = zipProcWith A.sub
-
-instance (A.PseudoRing b, A.IntegerConstant b) => Ring.C (T p a b) where
-   one = pure A.one
-   fromInteger n = pure (A.fromInteger' n)
-   (*) = zipProcWith A.mul
-
-instance (A.Field b, A.RationalConstant b) => Field.C (T p a b) where
-   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
-   (/) = zipProcWith A.fdiv
-
-
-instance (A.PseudoRing b, A.Real b, A.IntegerConstant b) => P.Num (T p a b) where
-   fromInteger n = pure (A.fromInteger' n)
-   negate = mapProc A.neg
-   (+) = zipProcWith A.add
-   (-) = zipProcWith A.sub
-   (*) = zipProcWith A.mul
-   abs = mapProc A.abs
-   signum = mapProc A.signum
-
-instance (A.Field b, A.Real b, A.RationalConstant b) => P.Fractional (T p a b) where
-   fromRational x = pure (A.fromRational' x)
-   (/) = zipProcWith A.fdiv
-
-
-{- |
-Not quite the loop of ArrowLoop
-because we need a delay of one time step
-and thus an initialization value.
-
-For a real ArrowLoop.loop, that is a zero-delay loop,
-we would formally need a MonadFix instance of CodeGenFunction.
-But this will not become reality, since LLVM is not able to re-order code
-in a way that allows to access a result before creating the input.
--}
-loop ::
-   (Marshal.C c, Tuple.ValueOf c ~ cl) =>
-   Param.T p c -> T p (a,cl) (b,cl) -> T p a b
-loop initial (Cons next alloca start stop createIOContext deleteIOContext) =
-   Param.withValue initial $ \getInitial valueInitial -> Cons
-      (curry $ loopNext $ uncurry next)
-      alloca
-      (\(i,p) -> fmap (mapSnd ((,) (valueInitial i))) $ start p)
-      (loopStop stop)
-      (\p -> do
-         (ctx, param) <- createIOContext p
-         return (ctx, (getInitial p, param)))
-      deleteIOContext
-
-loopStop :: (context -> state -> m) -> context -> (c, state) -> m
-loopStop stop ctx (_c,s) = stop ctx s
-
-
-takeWhile ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (forall r. pl -> a -> CodeGenFunction r (Value Bool)) ->
-   Param.T p ph ->
-   T p a a
-takeWhile check selectParam = simple
-   (\p a () -> do
-      MaybeCont.guard =<< MaybeCont.lift (check p a)
-      return (a, ()))
-   (\p -> return (p, ()))
-   selectParam
-
-
-take ::
-   Param.T p Int ->
-   T p a a
-take len =
-   snd ^<<
-   Causal.takeWhile (A.cmp LLVM.CmpLT A.zero . fst) <<<
-   feedFst
-      (Sig.iterate (const A.dec) (return ())
-         (Param.wordInt $ max 0 ^<< len))
-
-
-{- |
-The first output value is the initial value.
-Thus 'integrate' delays by one sample compared with 'integrateSync'.
--}
-integrate ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, A.Additive al) =>
-   Param.T p a ->
-   T p al al
-integrate =
-   flip loop (arr snd &&& zipWithSimple A.add)
-
-integrateSync ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, A.Additive al) =>
-   Param.T p a ->
-   T p al al
-integrateSync =
-   flip loop ((\a -> (a,a)) ^<< zipWithSimple A.add)
diff --git a/src/Synthesizer/LLVM/CausalParameterized/ProcessValue.hs b/src/Synthesizer/LLVM/CausalParameterized/ProcessValue.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/ProcessValue.hs
+++ /dev/null
@@ -1,100 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{- |
-This module provides functions similar to
-"Synthesizer.LLVM.CausalParameterized.Process"
-but expects functions that operate on 'Value.T'.
-This way you can use common arithmetic operators
-instead of LLVM assembly functions.
--}
-module Synthesizer.LLVM.CausalParameterized.ProcessValue (
---   simple,
-   mapAccum, map, mapSimple, zipWith, zipWithSimple,
-   takeWhile,
-   ) where
-
-import Synthesizer.LLVM.CausalParameterized.ProcessPrivate (T)
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate as CausalP
-import qualified Synthesizer.LLVM.Causal.ProcessValue as CausalV
-import qualified Synthesizer.LLVM.Simple.Value as Value
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-
-import qualified LLVM.Core as LLVM
-
-import Prelude hiding (map, zipWith, takeWhile)
-
-
-{-
-simple ::
-   (Storable startParamTuple,
-    Storable nextParamTuple,
-    Tuple.Value startParamTuple, Tuple.ValueOf startParamTuple ~ startParamValue,
-    Tuple.Value nextParamTuple, Tuple.ValueOf nextParamTuple ~ nextParamValue,
-    Memory.C startParamValue,
-    Memory.C nextParamValue,
-    Memory.C state) =>
-   (Value.T nextParamValue ->
-    Value.T a -> Value.T state -> Value.Maybe (Value.T b, Value.T state)) ->
-   (Value.T startParamValue -> Value.T state) ->
-   Param.T p nextParamTuple ->
-   Param.T p startParamTuple -> T p a b
-simple f start =
-   CausalP.simple
-      (\p a s ->
-         Value.flattenMaybe $
-         next
-            (Value.constantValue p)
-            (Value.constantValue a)
-            (Value.constantValue s))
-      (Value.unlift1 start)
--}
-
-map ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (Value.T pl -> Value.T a -> Value.T b) ->
-   Param.T p ph ->
-   T p a b
-map f = CausalP.map (Value.unlift2 f)
-
-mapSimple ::
-   (Value.T a -> Value.T b) ->
-   T p a b
-mapSimple = CausalV.map
-
-zipWith ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (Value.T pl -> Value.T a -> Value.T b -> Value.T c) ->
-   Param.T p ph -> T p (a,b) c
-zipWith f =
-   CausalP.zipWith (Value.unlift3 f)
-
-zipWithSimple ::
-   (Value.T a -> Value.T b -> Value.T c) ->
-   T p (a,b) c
-zipWithSimple = CausalV.zipWith
-
-mapAccum ::
-   (Marshal.C pnh, Tuple.ValueOf pnh ~ pnl,
-    Marshal.C psh, Tuple.ValueOf psh ~ psl,
-    Memory.C s) =>
-   (Value.T pnl -> Value.T a -> Value.T s -> (Value.T b, Value.T s)) ->
-   (Value.T psl -> Value.T s) ->
-   Param.T p pnh ->
-   Param.T p psh ->
-   T p a b
-mapAccum next start =
-   CausalP.mapAccum
-      (Value.unlift3 next)
-      (Value.unlift1 start)
-
-takeWhile ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (Value.T pl -> Value.T a -> Value.T (LLVM.Value Bool)) ->
-   Param.T p ph ->
-   T p a a
-takeWhile check =
-   CausalP.takeWhile (Value.unlift2 check)
diff --git a/src/Synthesizer/LLVM/CausalParameterized/RingBuffer.hs b/src/Synthesizer/LLVM/CausalParameterized/RingBuffer.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/RingBuffer.hs
+++ /dev/null
@@ -1,59 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TypeFamilies #-}
-module Synthesizer.LLVM.CausalParameterized.RingBuffer (
-   T, track, trackConst,
-   index, oldest,
-   ) where
-
-import Synthesizer.LLVM.RingBuffer
-
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate as CausalP
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Tuple as Tuple
-
-
-{- |
-@track initial time@ tracks the last @time@ sample values
-including the current one.
-The values before the actual input data are filled with @initial@.
-The values can be accessed using 'index' with indices
-ranging from 0 to @time@.
-
-The @time@ parameter must be non-negative.
-
-The initial value is also needed for determining the ring buffer element type.
--}
-track ::
-   (Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> Param.T p Int -> CausalP.T p al (T al)
-track initial time =
-   Param.withValue initial $ \getInitial valueInitial ->
-   Param.withValue (Param.wordInt time) $ \getTime valueTime ->
-      CausalP.Cons
-         (trackNext valueTime)
-         (return ())
-         (\(x, size) -> trackStart valueTime (valueInitial x, size))
-         trackStop
-         (trackCreate getInitial getTime)
-         trackDelete
-
-{- |
-Initialize with zero without the need of a Haskell zero value.
-
-We cannot get rid of the type 'a' so easily,
-because we need its Storable instance
-for allocating the buffer on the Haskell side.
--}
-trackConst :: (Memory.C al) => al -> Param.T p Int -> CausalP.T p al (T al)
-trackConst initial time =
-   Param.withValue (Param.wordInt time) $ \getTime valueTime ->
-      CausalP.Cons
-         (trackNext valueTime)
-         (return ())
-         (\size -> trackStart valueTime (initial, size))
-         trackStop
-         (trackConstCreate getTime)
-         trackDelete
diff --git a/src/Synthesizer/LLVM/CausalParameterized/RingBufferForward.hs b/src/Synthesizer/LLVM/CausalParameterized/RingBufferForward.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/CausalParameterized/RingBufferForward.hs
+++ /dev/null
@@ -1,295 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.CausalParameterized.RingBufferForward (
-   T, track, trackSkip, trackSkipHold,
-   index,
-   ) where
-
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate
-                                                              as CausalPrivP
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.SignalPrivate as SigP
-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*))
-import Synthesizer.LLVM.RingBuffer (MemoryPtr)
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Control as C
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value)
-
-import Control.Arrow ((<<<))
-import Control.Applicative (pure)
-import Data.Tuple.HT (mapSnd)
-
-import Data.Word (Word)
-
-import Prelude hiding (length)
-
-
-{- |
-This type is very similar to 'Synthesizer.LLVM.RingBuffer.T'
-but differs in several details:
-
-* It stores values in time order,
-  whereas 'Synthesizer.LLVM.RingBuffer.T' stores in opposite order.
-
-* Since it stores future values it is not causal
-  and can only track signal generators.
-
-* There is no need for an initial value.
-
-* It stores one value less than 'Synthesizer.LLVM.RingBuffer.T'
-  since it is meant to provide infixes of the signal
-  rather than providing the basis for a delay line.
-
-Those differences in detail would not justify a new type,
-you could achieve the same by a combination of
-'Synthesizer.LLVM.RingBuffer.track'
-and
-'Synthesizer.LLVM.CausalParameterized.Process.skip'.
-The fundamental problem of this combination is
-that it requires to keep the ring buffer alive
-longer than the providing signal exists.
-This is not possible with the current design.
-That's why we provide the combination of @track@ and @skip@
-in a way that does not suffer from that problem.
-This functionality is critical for
-'Synthesizer.LLVM.CausalParameterized.Helix.dynamic'.
--}
-data T a =
-   Cons {
-      buffer :: Value (MemoryPtr a),
-      length :: Value Word,
-      current :: Value Word
-   }
-
-{- |
-This function does not check for range violations.
-If the ring buffer was generated by @track time@,
-then the minimum index is zero and the maximum index is @time-1@.
-Index zero refers to the current sample
-and index @time-1@ refers to the one that is farthermost in the future.
--}
-index :: (Memory.C a) => Value Word -> T a -> CodeGenFunction r a
-index i rb = do
-   k <- flip A.irem (length rb) =<< A.add (current rb) i
-   Memory.load =<< LLVM.getElementPtr (buffer rb) (k, ())
-
-
-{- |
-@track time signal@ bundles @time@ successive values of @signal@.
-The values can be accessed using 'index' with indices
-ranging from 0 to @time-1@.
-
-The @time@ parameter must be non-negative.
--}
-track :: (Memory.C a) => Param.T p Int -> SigP.T p a -> SigP.T p (T a)
-track time input = trackSkip time input $* 1
-
-{- |
-@trackSkip time input $* skips@
-is like
-@Process.skip (track time input) $* skips@
-but this composition would require a @Memory@ constraint for 'T'
-which we cannot provide.
--}
-trackSkip ::
-   (Memory.C a) =>
-   Param.T p Int -> SigP.T p a -> CausalP.T p (Value Word) (T a)
-trackSkip time (SigP.Cons next alloca start stop create delete) =
-   Param.withValue (Param.wordInt time) $ \getTime valueTime ->
-      CausalPrivP.Cons
-         (trackNext next valueTime)
-         alloca
-         (trackStart start valueTime)
-         (trackStop stop)
-         (trackCreate create getTime)
-         (trackDelete delete)
-
-{- |
-Like @trackSkip@ but repeats the last buffer content
-when the end of the input signal is reached.
-The returned 'Bool' flag is 'True' if a skip could be performed completely
-and it is 'False' if the skip exceeds the end of the input.
-That is, once a 'False' is returned all following values are tagged with 'False'.
-The returned 'Word' value is the number of actually skipped values.
-This lags one step behind the input of skip values.
-The number of an actual number of skips
-is at most the number of requested skips.
-If the flag is 'False', then the number of actual skips is zero.
-The converse does not apply.
-
-If the input signal is too short, the output is undefined.
-(Before the available data the buffer will be filled with arbitrary values.)
-We could fill the buffer with zeros,
-but this would require an Arithmetic constraint
-and the generated signal would not be very meaningful.
-We could also return an empty signal if the input is too short.
-However this would require a permanent check.
--}
-trackSkipHold, trackSkipHold_ ::
-   (Memory.C a) =>
-   Param.T p Int -> SigP.T p a ->
-   CausalP.T p (Value Word) ((Value Bool, Value Word), T a)
-trackSkipHold time xs =
-   (CausalP.zipWithSimple
-       (\b ((c,x), buf) -> do
-          y <- C.select b x A.zero
-          return ((c, y), buf))
-      $< (CausalP.delay1 (pure False) $* SigP.constant (pure True)))
-{-
-   (CausalPV.zipWithSimple (\b ((c,x), buf) -> ((c, b ?? (x,0)), buf))
-      $< (CausalP.delay1 (pure False) $* SigP.constant (pure True)))
--}
-   <<<
-   trackSkipHold_ time xs
-
-trackSkipHold_ time (SigP.Cons next alloca start stop create delete) =
-   (Param.withValue (Param.wordInt time) $ \getTime valueTime ->
-      CausalPrivP.Cons
-         (trackNextHold next valueTime)
-         alloca
-         (trackStartHold start valueTime)
-         (trackStopHold stop)
-         (trackCreate create getTime)
-         (trackDelete delete))
-
-
-trackNext ::
-   (Memory.C al, Tuple.Phi z,
-    Tuple.Phi state, Tuple.Undefined state) =>
-   (forall z0. (Tuple.Phi z0) =>
-    context -> local -> state -> MaybeCont.T r z0 (al, state)) ->
-   (tl -> Value Word) ->
-   (context, (tl, Value (MemoryPtr al))) -> local ->
-   Value Word ->
-   (Value Word, (state, Value Word)) ->
-   MaybeCont.T r z (T al, (Value Word, (state, Value Word)))
-trackNext next valueTime (context, (size,ptr)) local n1 (n0, statePos) = do
-   let size0 = valueTime size
-   (state3, pos3) <-
-      MaybeCont.fromMaybe $ fmap snd $
-      MaybeCont.fixedLengthLoop n0 statePos $ \(state0, pos0) -> do
-         (a, state1) <- next context local state0
-         MaybeCont.lift $
-            fmap ((,) state1) $ storeNext (size0,ptr) a pos0
-   return (Cons ptr size0 pos3, (n1, (state3, pos3)))
-
-trackStart ::
-   (LLVM.IsSized am, Tuple.Phi state, Tuple.Undefined state) =>
-   (param -> CodeGenFunction r (context, state)) ->
-   (tl -> Value Word) ->
-   (param, tl) ->
-   CodeGenFunction r
-      ((context, (tl, Value (LLVM.Ptr am))),
-       (Value Word, (state, Value Word)))
-trackStart start valueTime (param, size) = do
-   (context, state) <- start param
-   let size0 = valueTime size
-   ptr <- LLVM.arrayMalloc size0
-   return ((context, (size,ptr)), (size0, (state, A.zero)))
-
-trackStop ::
-   (LLVM.IsType am) =>
-   (context -> state -> CodeGenFunction r ()) ->
-   (context, (tl, Value (LLVM.Ptr am))) ->
-   (Value Word, (state, Value Word)) ->
-   CodeGenFunction r ()
-trackStop stop (context, (_size,ptr)) (_n, (state, _remain)) = do
-   LLVM.free ptr
-   stop context state
-
-
-trackNextHold ::
-   (Memory.C al, Tuple.Phi z,
-    Tuple.Phi state, Tuple.Undefined state) =>
-   (forall z0. (Tuple.Phi z0) =>
-    context -> local -> state -> MaybeCont.T r z0 (al, state)) ->
-   (tl -> Value Word) ->
-   (context, (tl, Value (MemoryPtr al))) -> local ->
-   Value Word ->
-   (Value Word, (Maybe.T state, Value Word)) ->
-   MaybeCont.T r z
-      (((Value Bool, Value Word), T al),
-       (Value Word, (Maybe.T state, Value Word)))
-trackNextHold
-   next valueTime (context, (size,ptr)) local nNext (n0, (mstate0, pos0)) =
-      MaybeCont.lift $ do
-   let size0 = valueTime size
-   (n3, (pos3, state3)) <-
-      Maybe.run mstate0
-         (return (n0, (pos0, mstate0)))
-         (\state0 ->
-            Maybe.loopWithExit (n0, (state0, pos0))
-               (\(n1, (state1, pos1)) -> do
-                  cont <- A.cmp LLVM.CmpGT n1 A.zero
-                  fmap (mapSnd ((,) n1 . (,) pos1)) $
-                     C.ifThen cont
-                        (Maybe.nothing, Maybe.just state1)
-                        (do aState <-
-                              MaybeCont.toMaybe $ next context local state1
-                            return (aState, fmap snd aState)))
-               (\((a,state), (n1, (pos1, _mstate))) -> do
-                  pos2 <- storeNext (size0,ptr) a pos1
-                  n2 <- A.dec n1
-                  return (n2, (state, pos2))))
-   skipped <- A.sub n0 n3
-   return (((Maybe.isJust state3, skipped), Cons ptr size0 pos3),
-           (nNext, (state3, pos3)))
-
-storeNext ::
-   (Memory.C al) =>
-   (Value Word, Value (MemoryPtr al)) ->
-   al -> Value Word -> CodeGenFunction r (Value Word)
-storeNext (size0,ptr) a pos0 = do
-   Memory.store a =<< LLVM.getElementPtr ptr (pos0, ())
-   pos1 <- A.inc pos0
-   cont <- A.cmp LLVM.CmpLT pos1 size0
-   C.select cont pos1 A.zero
-
-
-trackStartHold ::
-   (LLVM.IsSized am,
-    Tuple.Phi state, Tuple.Undefined state) =>
-   (param -> CodeGenFunction r (context, state)) ->
-   (tl -> Value Word) ->
-   (param, tl) ->
-   CodeGenFunction r
-      ((context, (tl, Value (LLVM.Ptr am))),
-       (Value Word, (Maybe.T state, Value Word)))
-trackStartHold start valueTime (param, size) = do
-   (context, state) <- start param
-   let size0 = valueTime size
-   ptr <- LLVM.arrayMalloc size0
-   return ((context, (size,ptr)), (size0, (Maybe.just state, A.zero)))
-
-trackStopHold ::
-   (LLVM.IsType am) =>
-   (context -> state -> CodeGenFunction r ()) ->
-   (context, (tl, Value (LLVM.Ptr am))) ->
-   (Value Word, (Maybe.T state, Value Word)) ->
-   CodeGenFunction r ()
-trackStopHold stop (context, (_size,ptr)) (_n, (state, _remain)) = do
-   LLVM.free ptr
-   Maybe.for state $ stop context
-
-
-trackCreate ::
-   (p -> IO (ioContext, param)) ->
-   (p -> t) ->
-   p ->
-   IO (ioContext, (param, t))
-trackCreate create getTime p = do
-   (context, param) <- create p
-   return (context, (param, getTime p))
-
-trackDelete :: (ioContext -> IO ()) -> ioContext -> IO ()
-trackDelete = id
diff --git a/src/Synthesizer/LLVM/Complex.hs b/src/Synthesizer/LLVM/Complex.hs
--- a/src/Synthesizer/LLVM/Complex.hs
+++ b/src/Synthesizer/LLVM/Complex.hs
@@ -3,25 +3,28 @@
 module Synthesizer.LLVM.Complex (
    Complex.T(Complex.real, Complex.imag),
    Struct,
-   (Complex.+:),
+   (+:),
    Complex.cis,
    Complex.scale,
    constOf, unfold,
    ) where
 
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Value as Value
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Tuple as Tuple
 
 import qualified LLVM.Core as LLVM
 import LLVM.Core (Value, ConstValue, IsConst)
 
-import qualified Type.Data.Num.Decimal      as TypeNum
+import qualified Type.Data.Num.Decimal as TypeNum
 
 import Control.Applicative (liftA2)
 
 import qualified Number.Complex as Complex
+import Number.Complex ((+:))
 
 
 type Struct a = LLVM.Struct (a, (a, ()))
@@ -38,16 +41,16 @@
    Value (Struct a) -> Complex.T (Value.T (Value a))
 unfold x =
    Value.lift0 (LLVM.extractvalue x TypeNum.d0)
-   Complex.+:
+   +:
    Value.lift0 (LLVM.extractvalue x TypeNum.d1)
 
 
 instance (Tuple.Undefined a) => Tuple.Undefined (Complex.T a) where
-   undef = (Complex.+:) Tuple.undef Tuple.undef
+   undef = Tuple.undef +: Tuple.undef
 
 instance (Tuple.Phi a) => Tuple.Phi (Complex.T a) where
    phi bb v =
-      liftA2 (Complex.+:)
+      liftA2 (+:)
          (Tuple.phi bb (Complex.real v))
          (Tuple.phi bb (Complex.imag v))
    addPhi bb x y = do
@@ -59,7 +62,7 @@
    (Memory.C l) =>
    Memory.Record r (Struct (Memory.Struct l)) (Complex.T l)
 memory =
-   liftA2 (Complex.+:)
+   liftA2 (+:)
       (Memory.element Complex.real TypeNum.d0)
       (Memory.element Complex.imag TypeNum.d1)
 
@@ -69,3 +72,36 @@
    store = Memory.storeRecord memory
    decompose = Memory.decomposeRecord memory
    compose = Memory.composeRecord memory
+
+
+
+instance (MultiValue.C a) => MultiValue.C (Complex.T a) where
+   type Repr (Complex.T a) = Complex.T (MultiValue.Repr a)
+   cons x =
+      consMV
+         (MultiValue.cons $ Complex.real x)
+         (MultiValue.cons $ Complex.imag x)
+   undef = consMV MultiValue.undef MultiValue.undef
+   zero = consMV MultiValue.zero MultiValue.zero
+   phi bb a =
+      case deconsMV a of
+         (a0,a1) -> liftA2 consMV (MultiValue.phi bb a0) (MultiValue.phi bb a1)
+   addPhi bb a b =
+      case (deconsMV a, deconsMV b) of
+         ((a0,a1), (b0,b1)) ->
+            MultiValue.addPhi bb a0 b0 >> MultiValue.addPhi bb a1 b1
+
+consMV :: MultiValue.T a -> MultiValue.T a -> MultiValue.T (Complex.T a)
+consMV (MultiValue.Cons a) (MultiValue.Cons b) = MultiValue.Cons (a+:b)
+
+deconsMV :: MultiValue.T (Complex.T a) -> (MultiValue.T a, MultiValue.T a)
+deconsMV (MultiValue.Cons x) =
+   (MultiValue.Cons $ Complex.real x, MultiValue.Cons $ Complex.imag x)
+
+
+instance (Marshal.C a) => Marshal.C (Complex.T a) where
+   pack x =
+      LLVM.consStruct
+         (Marshal.pack $ Complex.real x)
+         (Marshal.pack $ Complex.imag x)
+   unpack = LLVM.uncurryStruct $ \a b -> Marshal.unpack a +: Marshal.unpack b
diff --git a/src/Synthesizer/LLVM/ConstantPiece.hs b/src/Synthesizer/LLVM/ConstantPiece.hs
--- a/src/Synthesizer/LLVM/ConstantPiece.hs
+++ b/src/Synthesizer/LLVM/ConstantPiece.hs
@@ -10,24 +10,15 @@
    Struct,
    parameterMemory,
    flatten,
-   piecewiseConstant,
-   lazySize,
+   causalMap,
    ) where
 
-import qualified Synthesizer.LLVM.Parameterized.SignalPrivate as SigP
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as Sig
-
-import qualified Synthesizer.LLVM.Storable.LazySizeIterator as SizeIt
-import qualified Data.StorableVector.Lazy.Pattern as SVP
-
-import qualified Synthesizer.LLVM.EventIterator as EventIt
-import qualified Data.EventList.Relative.BodyTime as EventList
-import qualified Numeric.NonNegative.Wrapper as NonNeg
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Private as Sig
 
-import qualified LLVM.DSL.Parameter as Param
+import qualified LLVM.DSL.Expression as Expr
 
 import qualified LLVM.Extra.MaybeContinuation as Maybe
-import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Arithmetic as A
@@ -38,9 +29,10 @@
 
 import Type.Data.Num.Decimal (d0, d1)
 
+import Data.Tuple.HT (mapSnd)
 import Data.Word (Word)
 
-import Control.Applicative (liftA2)
+import Control.Applicative (liftA2, (<$>))
 
 import NumericPrelude.Numeric ()
 import NumericPrelude.Base
@@ -48,6 +40,9 @@
 
 data T a = Cons (Value Word) a
 
+instance Functor T where
+   fmap f (Cons len y) = Cons len (f y)
+
 instance (Tuple.Phi a) => Tuple.Phi (T a) where
    phi bb (Cons len y) =
       liftA2 Cons (Tuple.phi bb len) (Tuple.phi bb y)
@@ -78,69 +73,24 @@
    compose = Memory.composeRecord parameterMemory
 
 
-flatten ::
-   (Sig.C signal, Memory.C value) =>
-   signal (T value) ->
-   signal value
-flatten = Sig.alter (\(Sig.Core next start stop) ->
-   Sig.Core
-      (\context state0 -> do
+causalMap ::
+   (Expr.Aggregate a am, Expr.Aggregate b bm) =>
+   (a -> b) -> Causal.T (T am) (T bm)
+causalMap f = Causal.map (\(Cons len y) -> Cons len <$> Expr.unliftM1 f y)
+
+
+flatten :: (Memory.C a) => Sig.T (T a) -> Sig.T a
+flatten (Sig.Cons next start stop) =
+   Sig.Cons
+      (\global local state0 -> do
          ~(Cons length1 y1, s1) <-
             Maybe.fromBool $
             whileLoop (valueOf True, state0)
                (\(cont, (Cons len _y, _s)) ->
                   LLVM.and cont =<< A.cmp LLVM.CmpEQ len A.zero)
                (\(_cont, (Cons _len _y, s)) ->
-                  Maybe.toBool $ next context s)
+                  Maybe.toBool $ next global local s)
          length2 <- Maybe.lift (A.dec length1)
          return (y1, (Cons length2 y1, s1)))
-      (fmap ((,) (Cons A.zero Tuple.undef)) . start)
-      (stop . snd))
-
-
-piecewiseConstant ::
-   (Marshal.C a, Tuple.ValueOf a ~ value, Marshal.Struct a ~ struct) =>
-   Param.T p (EventList.T NonNeg.Int a) ->
-   SigP.T p (T value)
-piecewiseConstant evs = SigP.Cons
-   (\stable yPtr () -> do
-      len <- Maybe.lift $ do
-         nextFn <-
-            LLVM.staticNamedFunction
-               "ConstantPiece.piecewiseConstant.nextChunk"
-               EventIt.nextCallBack
-         LLVM.call nextFn stable yPtr
-      Maybe.guard =<<
-         Maybe.lift (A.cmp LLVM.CmpNE len A.zero)
-      y <- Maybe.lift $ Memory.load yPtr
-      return (Cons len y, ()))
-   LLVM.alloca
-   return
-   (const $ const $ return ())
-   (\p -> do
-      stable <- EventIt.new (Param.get evs p)
-      return (stable, (stable, ())))
-   EventIt.dispose
-
-
-lazySize ::
-   Param.T p SVP.LazySize ->
-   SigP.T p (T ())
-lazySize size = SigP.Cons
-   (\stable () () -> do
-      len <- Maybe.lift $ do
-         nextFn <-
-            LLVM.staticNamedFunction
-               "ConstantPiece.lazySize.nextChunk"
-               SizeIt.nextCallBack
-         LLVM.call nextFn stable
-      Maybe.guard =<<
-         Maybe.lift (A.cmp LLVM.CmpNE len A.zero)
-      return (Cons len (), ()))
-   (return ())
-   return
-   (const $ const $ return ())
-   (\p -> do
-      stable <- SizeIt.new (Param.get size p)
-      return (stable, (stable, ())))
-   SizeIt.dispose
+      (mapSnd ((,) (Cons A.zero Tuple.undef)) <$> start)
+      stop
diff --git a/src/Synthesizer/LLVM/EventIterator.hs b/src/Synthesizer/LLVM/EventIterator.hs
--- a/src/Synthesizer/LLVM/EventIterator.hs
+++ b/src/Synthesizer/LLVM/EventIterator.hs
@@ -6,7 +6,7 @@
 import qualified Data.EventList.Relative.BodyTime as EventList
 import qualified Numeric.NonNegative.Wrapper as NonNeg
 
-import qualified LLVM.Extra.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
 import qualified LLVM.Core as LLVM
 
 import Foreign.StablePtr
@@ -28,10 +28,10 @@
 type MarshalPtr a = LLVM.Ptr (Marshal.Struct a)
 
 
-foreign import ccall "&nextConstant"
+foreign import ccall "&nextConstantExp"
    nextCallBack :: FunPtr (StablePtr (T a) -> MarshalPtr a -> IO Word)
 
-foreign export ccall "nextConstant"
+foreign export ccall "nextConstantExp"
    next :: StablePtr (T a) -> MarshalPtr a -> IO Word
 
 
diff --git a/src/Synthesizer/LLVM/Filter/Allpass.hs b/src/Synthesizer/LLVM/Filter/Allpass.hs
--- a/src/Synthesizer/LLVM/Filter/Allpass.hs
+++ b/src/Synthesizer/LLVM/Filter/Allpass.hs
@@ -8,30 +8,28 @@
 {-# LANGUAGE DeriveTraversable #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Synthesizer.LLVM.Filter.Allpass (
-   Parameter, parameter,
-   CascadeParameter, flangerParameter, flangerParameterPlain,
+   Parameter, Allpass.parameter,
+   CascadeParameter(CascadeParameter), flangerParameter,
+   cascadeParameterMultiValue, cascadeParameterUnMultiValue,
    causal, cascade, phaser,
    cascadePipeline, phaserPipeline,
    causalPacked, cascadePacked, phaserPacked,
-
-   causalP, cascadeP, phaserP,
-   causalPackedP, cascadePackedP, phaserPackedP,
    ) where
 
 import Synthesizer.Plain.Filter.Recursive.Allpass (Parameter(Parameter))
 import qualified Synthesizer.Plain.Filter.Recursive.Allpass as Allpass
 import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1
 
-import qualified Synthesizer.Plain.Modifier as Modifier
 import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1L
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
-import qualified Synthesizer.LLVM.Causal.ProcessValue as CausalV
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
 import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Causal.Functional as F
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as Serial
 
+import qualified LLVM.DSL.Expression as Expr
+
+import qualified LLVM.Extra.Multi.Value.Marshal as MarshalMV
 import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Vector as Vector
@@ -41,8 +39,6 @@
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction)
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Base.Proxy (Proxy(Proxy))
@@ -55,9 +51,10 @@
 
 import qualified Data.Traversable as Trav
 import qualified Data.Foldable as Fold
-import Data.Tuple.HT (mapPair)
+import Data.Tuple.HT (mapFst)
 
 import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Module as Module
 
 import NumericPrelude.Numeric
 import NumericPrelude.Base
@@ -73,6 +70,14 @@
 instance Tuple.Zero a => Tuple.Zero (Parameter a) where
    zero = Tuple.zeroPointed
 
+instance
+   (Expr.Aggregate e mv) =>
+      Expr.Aggregate (Parameter e) (Parameter mv) where
+   type MultiValuesOf (Parameter e) = Parameter (Expr.MultiValuesOf e)
+   type ExpressionsOf (Parameter mv) = Parameter (Expr.ExpressionsOf mv)
+   bundle = Trav.traverse Expr.bundle
+   dissect = fmap Expr.dissect
+
 instance (Memory.C a) => Memory.C (Parameter a) where
    type Struct (Parameter a) = Memory.Struct a
    load = Memory.loadNewtype Parameter
@@ -84,19 +89,15 @@
    pack (Parameter k) = Marshal.pack k
    unpack = Parameter . Marshal.unpack
 
+instance (MarshalMV.C a) => MarshalMV.C (Parameter a) where
+   pack (Parameter k) = MarshalMV.pack k
+   unpack = Parameter . MarshalMV.unpack
+
 instance (Storable.C a) => Storable.C (Parameter a) where
    load = Storable.loadNewtype Parameter Parameter
    store = Storable.storeNewtype Parameter (\(Parameter k) -> k)
 
 
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (Parameter a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
-
-instance LLVM.IsTuple a => LLVM.IsTuple (Parameter a) where
-   tupleDesc = Class.tupleDescFoldable
--}
-
 instance (Tuple.Value a) => Tuple.Value (Parameter a) where
    type ValueOf (Parameter a) = Parameter (Tuple.ValueOf a)
    valueOf = Tuple.valueOfFunctor
@@ -106,6 +107,7 @@
    vectorValueOf = fmap Tuple.vectorValueOf . Trav.sequenceA
 
 instance (MultiValue.C a) => MultiValue.C (Allpass.Parameter a) where
+   type Repr (Parameter a) = Parameter (MultiValue.Repr a)
    cons = paramFromPlainValue . MultiValue.cons . Allpass.getParameter
 
    undef = paramFromPlainValue MultiValue.undef
@@ -121,6 +123,7 @@
          (plainFromParamValue b)
 
 instance (MultiVector.C a) => MultiVector.C (Allpass.Parameter a) where
+   type Repr n (Parameter a) = Parameter (MultiVector.Repr n a)
    cons = paramFromPlainVector . MultiVector.cons . fmap Allpass.getParameter
    undef = paramFromPlainVector MultiVector.undef
    zero = paramFromPlainVector MultiVector.zero
@@ -171,12 +174,6 @@
    MultiValue.lift1 Allpass.getParameter
 
 
-instance (Value.Flatten a) => Value.Flatten (Parameter a) where
-   type Registers (Parameter a) = Parameter (Value.Registers a)
-   flattenCode = Value.flattenCodeTraversable
-   unfoldCode = Value.unfoldCodeTraversable
-
-
 instance (Vector.Simple v) => Vector.Simple (Parameter v) where
    type Element (Parameter v) = Parameter (Vector.Element v)
    type Size (Parameter v) = Vector.Size v
@@ -191,12 +188,6 @@
    makeArgs = id
 
 
-parameter ::
-   (A.Transcendental a, A.RationalConstant a) =>
-   a -> a -> CodeGenFunction r (Parameter a)
-parameter = Value.unlift2 Allpass.parameter
-
-
 newtype CascadeParameter n a =
    CascadeParameter (Allpass.Parameter a)
       deriving
@@ -219,19 +210,15 @@
    pack (CascadeParameter k) = Marshal.pack k
    unpack = CascadeParameter . Marshal.unpack
 
+instance (MarshalMV.C a) => MarshalMV.C (CascadeParameter n a) where
+   pack (CascadeParameter k) = MarshalMV.pack k
+   unpack = CascadeParameter . MarshalMV.unpack
+
 instance (Storable.C a) => Storable.C (CascadeParameter n a) where
    load = Storable.loadNewtype CascadeParameter id
    store = Storable.storeNewtype CascadeParameter id
 
 
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (CascadeParameter n a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
-
-instance LLVM.IsTuple a => LLVM.IsTuple (CascadeParameter n a) where
-   tupleDesc = Class.tupleDescFoldable
--}
-
 instance (Tuple.Value a) => Tuple.Value (CascadeParameter n a) where
    type ValueOf (CascadeParameter n a) = Parameter (Tuple.ValueOf a)
    valueOf (CascadeParameter a) = Tuple.valueOf a
@@ -245,6 +232,7 @@
       fmap Tuple.vectorValueOf . Trav.traverse (\(CascadeParameter k) -> k)
 
 instance (MultiValue.C a) => MultiValue.C (CascadeParameter n a) where
+   type Repr (CascadeParameter n a) = Parameter (MultiValue.Repr a)
    cons (CascadeParameter a) = cascadeFromParamValue $ MultiValue.cons a
 
    undef = cascadeFromParamValue MultiValue.undef
@@ -259,7 +247,8 @@
          (paramFromCascadeValue a)
          (paramFromCascadeValue b)
 
-instance (MultiVector.C a) => MultiVector.C (CascadeParameter n a) where
+instance (MultiVector.C a) => MultiVector.C (CascadeParameter m a) where
+   type Repr n (CascadeParameter m a) = Parameter (MultiVector.Repr n a)
    cons =
       cascadeFromParamVector . MultiVector.cons .
       fmap (\(CascadeParameter a) -> a)
@@ -308,12 +297,7 @@
    MultiValue.T (Allpass.Parameter a)
 paramFromCascadeValue = MultiValue.lift1 id
 
-instance (Value.Flatten a) => Value.Flatten (CascadeParameter n a) where
-   type Registers (CascadeParameter n a) = CascadeParameter n (Value.Registers a)
-   flattenCode = Value.flattenCodeTraversable
-   unfoldCode = Value.unfoldCodeTraversable
 
-
 instance (Vector.Simple v) => Vector.Simple (CascadeParameter n v) where
    type Element (CascadeParameter n v) = CascadeParameter n (Vector.Element v)
    type Size (CascadeParameter n v) = Vector.Size v
@@ -328,76 +312,64 @@
    makeArgs = id
 
 
-flangerParameter ::
-   (A.Transcendental a, A.RationalConstant a, TypeNum.Natural n) =>
-   Proxy n -> a ->
-   CodeGenFunction r (CascadeParameter n a)
-flangerParameter order =
-   Value.unlift1 (flangerParameterPlain order)
+instance
+   (Expr.Aggregate e mv, n ~ m) =>
+      Expr.Aggregate (CascadeParameter n e) (CascadeParameter m mv) where
+   type MultiValuesOf (CascadeParameter n e) =
+            CascadeParameter n (Expr.MultiValuesOf e)
+   type ExpressionsOf (CascadeParameter m mv) =
+            CascadeParameter m (Expr.ExpressionsOf mv)
+   bundle = Trav.traverse Expr.bundle
+   dissect = fmap Expr.dissect
 
-flangerParameterPlain ::
+
+flangerParameter ::
    (Trans.C a, TypeNum.Natural n) =>
    Proxy n -> a -> CascadeParameter n a
-flangerParameterPlain order freq =
+flangerParameter order freq =
    CascadeParameter $
    Allpass.flangerParameter (TypeNum.integralFromProxy order) freq
 
 
-modifier ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-   Modifier.Simple
-      -- (Allpass.State (Value.T v))
-      (Value.T v, Value.T v)
-      (Parameter (Value.T a))
-      (Value.T v) (Value.T v)
-modifier =
-   Allpass.firstOrderModifier
-
-{-
-For Allpass cascade you may use the 'Causal.pipeline' function.
--}
 causal ::
-   (Causal.C process,
-    A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   process (Parameter a, v) v
-causal =
-   Causal.fromModifier modifier
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v, Memory.C v) =>
+   Causal.T (Parameter a, v) v
+causal = Causal.fromModifier Allpass.firstOrderModifier
 
 
 replicateStage ::
-   (Causal.C process,
-    TypeNum.Natural n, Tuple.Phi b, Tuple.Undefined b) =>
+   (TypeNum.Natural n) =>
+   (Tuple.Phi a, Tuple.Undefined a) =>
+   (Tuple.Phi b, Tuple.Undefined b) =>
    Proxy n ->
-   process (Parameter a, b) b ->
-   process (CascadeParameter n a, b) b
+   Causal.T (Parameter a, b) b ->
+   Causal.T (CascadeParameter n a, b) b
 replicateStage order stg =
    Causal.replicateControlled
       (TypeNum.integralFromProxy order)
       (stg <<< first (arr (\(CascadeParameter p) -> p)))
 
 cascade ::
-   (Causal.C process,
-    A.RationalConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v,
-    TypeNum.Natural n) =>
-   process (CascadeParameter n a, v) v
-cascade =
-   replicateStage Proxy causal
+   (TypeNum.Natural n) =>
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v, Memory.C v) =>
+   (Tuple.Phi a, Tuple.Undefined a) =>
+   (Tuple.Phi v, Tuple.Undefined v) =>
+   Causal.T (CascadeParameter n a, v) v
+cascade = replicateStage Proxy causal
 
 halfVector ::
-   (Causal.C process, A.RationalConstant a, a ~ A.Scalar v, A.PseudoModule v) =>
-   process v v
-halfVector = CausalV.map (Value.fromRational' 0.5 *>)
+   (A.RationalConstant a, a ~ A.Scalar v, A.PseudoModule v) =>
+   Causal.T v v
+halfVector = CausalPriv.map (A.scale $ A.fromRational' 0.5)
 
 phaser ::
-   (Causal.C process,
-    A.RationalConstant a, A.RationalConstant v,
-    a ~ A.Scalar v, A.PseudoModule v, Memory.C v,
-    TypeNum.Natural n) =>
-   process (CascadeParameter n a, v) v
-phaser =
-   Causal.mix <<<
-   cascade &&& arr snd <<<
-   second halfVector
+   (TypeNum.Natural n) =>
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v, Memory.C v) =>
+   (Tuple.Phi a, Tuple.Undefined a) =>
+   (Tuple.Phi v, Tuple.Undefined v) =>
+   (A.RationalConstant a, a ~ A.Scalar v, A.PseudoModule v) =>
+   Causal.T (CascadeParameter n a, v) v
+phaser = (cascade + arr snd) <<< second halfVector
 
 
 paramFromCascadeParam ::
@@ -411,12 +383,11 @@
 but LLVM-2.6 does not yet do it.
 -}
 stage ::
-   (Causal.C process,
-    TypeNum.Positive n, MultiVector.C a,
+   (TypeNum.Positive n, MultiVector.C a,
     MultiVector.T n (CascadeParameter n a, a) ~ v,
     MultiValue.PseudoRing a, MultiValue.IntegerConstant a,
-    Marshal.C a) =>
-   Proxy n -> process v v
+    MarshalMV.C a) =>
+   Proxy n -> Causal.T v v
 stage _ =
    Causal.vectorize $
       uncurry MultiValue.zip
@@ -432,8 +403,8 @@
       MultiValue.unzip
 
 withSize ::
-   (Proxy n -> process (MultiValue.T (CascadeParameter n a), b) c) ->
-   process (MultiValue.T (CascadeParameter n a), b) c
+   (Proxy n -> Causal.T (mv (CascadeParameter n a), b) c) ->
+   Causal.T (mv (CascadeParameter n a), b) c
 withSize f = f Proxy
 
 {- |
@@ -443,12 +414,11 @@
 and we get a delay by the number of pipeline stages.
 -}
 cascadePipeline ::
-   (Causal.C process,
-    TypeNum.Positive n, MultiVector.C a,
+   (TypeNum.Positive n, MultiVector.C a,
     Tuple.ValueOf a ~ ar,
     MultiValue.PseudoRing a, MultiValue.IntegerConstant a,
-    Marshal.C a, Marshal.Vector n a) =>
-   process
+    MarshalMV.C a, MarshalMV.Vector n a) =>
+   Causal.T
       (MultiValue.T (CascadeParameter n a), MultiValue.T a)
       (MultiValue.T a)
 cascadePipeline = withSize $ \order ->
@@ -459,148 +429,82 @@
    uncurry MultiValue.zip
 
 vectorId ::
-   (Causal.C process) =>
-   Proxy n -> process (MultiVector.T n a) (MultiVector.T n a)
+   Proxy n -> Causal.T (MultiVector.T n a) (MultiVector.T n a)
 vectorId _ = Cat.id
 
 half ::
-   (Causal.C process, A.RationalConstant a, A.PseudoRing a) =>
-   process a a
-half = CausalV.map (Value.fromRational' 0.5 *)
-
-
-multiValue ::
-   (Tuple.ValueOf a ~ LLVM.Value a) =>
-   LLVM.Value a -> MultiValue.T a
-multiValue = MultiValue.Cons
-
-unmultiValue ::
-   (Tuple.ValueOf a ~ LLVM.Value a) =>
-   MultiValue.T a -> LLVM.Value a
-unmultiValue (MultiValue.Cons a) = a
-
-multiCascadeParam ::
-   (Tuple.ValueOf a ~ LLVM.Value a) =>
-   CascadeParameter n (LLVM.Value a) ->
-   MultiValue.T (CascadeParameter n a)
-multiCascadeParam (CascadeParameter a) =
-   MultiValue.Cons a
-
-phaserPipeline ::
-   (Causal.C process,
-    TypeNum.Positive n,
-    MultiValue.PseudoRing a, MultiValue.RationalConstant a,
-    Marshal.C a, Marshal.Vector n a, MultiVector.C a,
-    Tuple.ValueOf a ~ LLVM.Value a) =>
-   process
-      (CascadeParameter n (LLVM.Value a), LLVM.Value a)
-      (LLVM.Value a)
-phaserPipeline =
-   unmultiValue
-   ^<<
-   phaserPipelineMulti
-   <<^
-   mapPair (multiCascadeParam, multiValue)
-
-
-phaserPipelineMulti ::
-   (Causal.C process,
-    TypeNum.Positive n,
-    MultiValue.PseudoRing a, MultiValue.RationalConstant a,
-    Marshal.C a, Marshal.Vector n a, MultiVector.C a) =>
-   process
-      (MultiValue.T (CascadeParameter n a), MultiValue.T a)
-      (MultiValue.T a)
-phaserPipelineMulti = withSize $ \order ->
-   Causal.mix <<<
-   cascadePipeline &&&
-   (Causal.pipeline (vectorId order) <<^ snd) <<<
---   (Causal.delay (const zero) (const $ TypeNum.integralFromProxy order) <<^ snd) <<<
-   second half
+   (A.RationalConstant a, A.PseudoRing a) =>
+   Causal.T a a
+half = CausalPriv.map (A.mul (A.fromRational' 0.5))
 
 
 causalPacked,
   causalNonRecursivePacked ::
-   (Causal.C process,
-    Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   process (Parameter a, v) v
+   (Serial.Write v, Serial.Element v ~ a,
+    A.PseudoRing a, A.IntegerConstant a, Memory.C a,
+    A.PseudoRing v, A.IntegerConstant v) =>
+   Causal.T (Parameter a, v) v
 
 causalPacked =
    Filt1L.causalRecursivePacked <<<
-   (Causal.map
-       (\(Parameter k, _) ->
-           fmap Filt1.Parameter $ A.neg k) &&&
+   (CausalPriv.map (\(Parameter k, _) -> fmap Filt1.Parameter $ A.neg k) &&&
     causalNonRecursivePacked)
 
 causalNonRecursivePacked =
-   Causal.mapAccum
+   CausalPriv.mapAccum
       (\(Parameter k, v0) x1 -> do
          (_,v1) <- Serial.shiftUp x1 v0
          y <- A.add v1 =<< A.mul v0 =<< Serial.upsample k
-         let size = fromIntegral $ Serial.size v0
-         u0 <- Serial.extract (LLVM.valueOf $ size - 1) v0
+         u0 <- Serial.last v0
          return (y, u0))
       (return A.zero)
 
 cascadePacked, phaserPacked ::
-   (Causal.C process,
-    TypeNum.Natural n,
-    Serial.C v, Serial.Element v ~ a,
+   (TypeNum.Natural n,
+    Serial.Write v, Serial.Element v ~ a,
     A.PseudoRing a, A.IntegerConstant a, Memory.C a,
     A.PseudoRing v, A.RationalConstant v) =>
-   process (CascadeParameter n a, v) v
-cascadePacked =
-   replicateStage Proxy causalPacked
+   Causal.T (CascadeParameter n a, v) v
+cascadePacked = replicateStage Proxy causalPacked
 
 phaserPacked =
-   Causal.mix <<<
-   cascadePacked &&& arr snd <<<
-   second (Causal.map (A.mul (A.fromRational' 0.5)))
-
-
-
+   (cascadePacked + arr snd) <<<
+   second (CausalPriv.map (A.mul (A.fromRational' 0.5)))
 
 
-causalP ::
-   (A.RationalConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   CausalP.T p (Parameter a, v) v
-causalP = causal
-
-cascadeP ::
-   (A.RationalConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v,
-    TypeNum.Natural n) =>
-   CausalP.T p (CascadeParameter n a, v) v
-cascadeP = cascade
+-- ToDo: consistent naming with Exponential2
+cascadeParameterMultiValue ::
+   CascadeParameter n (MultiValue.T a) ->
+   MultiValue.T (CascadeParameter n a)
+cascadeParameterMultiValue (CascadeParameter k) =
+   MultiValue.Cons $ fmap (\(MultiValue.Cons a) -> a) k
 
-phaserP ::
-   (A.RationalConstant a, A.RationalConstant v,
-    a ~ A.Scalar v, A.PseudoModule v, Memory.C v,
-    TypeNum.Natural n) =>
-   CausalP.T p (CascadeParameter n a, v) v
-phaserP = phaser
+cascadeParameterUnMultiValue ::
+   MultiValue.T (CascadeParameter n a) ->
+   CascadeParameter n (MultiValue.T a)
+cascadeParameterUnMultiValue (MultiValue.Cons k) =
+   CascadeParameter $ fmap MultiValue.Cons k
 
 
-causalPackedP ::
-   (Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   CausalP.T p (Parameter a, v) v
-causalPackedP = causalPacked
-
-cascadePackedP, phaserPackedP ::
-   (TypeNum.Natural n,
-    Serial.C v, Serial.Element v ~ a,
-    A.PseudoRing a, A.IntegerConstant a, Memory.C a,
-    A.PseudoRing v, A.RationalConstant v) =>
-   CausalP.T p (CascadeParameter n a, v) v
-cascadePackedP = cascadePacked
-phaserPackedP = phaserPacked
+phaserPipelineMV ::
+   (TypeNum.Positive n,
+    MultiValue.PseudoRing a, MultiValue.RationalConstant a,
+    Marshal.C a, MarshalMV.Vector n a) =>
+   Causal.T
+      (MultiValue.T (CascadeParameter n a), MultiValue.T a)
+      (MultiValue.T a)
+phaserPipelineMV = withSize $ \order ->
+   Causal.mix <<<
+   cascadePipeline &&&
+   (Causal.pipeline (vectorId order) <<^ snd) <<<
+--   (Causal.delay (const zero) (const $ TypeNum.integralFromProxy order) <<^ snd) <<<
+   second half
 
-{-# DEPRECATED causalP          "use 'causal' instead" #-}
-{-# DEPRECATED cascadeP         "use 'cascade' instead" #-}
-{-# DEPRECATED phaserP          "use 'phaser' instead" #-}
-{-# DEPRECATED causalPackedP    "use 'causalPacked' instead" #-}
-{-# DEPRECATED cascadePackedP   "use 'cascadePacked' instead" #-}
-{-# DEPRECATED phaserPackedP    "use 'phaserPacked' instead" #-}
+phaserPipeline ::
+   (TypeNum.Positive n,
+    MultiValue.PseudoRing a, MultiValue.RationalConstant a,
+    Marshal.C a, MarshalMV.Vector n a) =>
+   Causal.T
+      (CascadeParameter n (MultiValue.T a), MultiValue.T a)
+      (MultiValue.T a)
+phaserPipeline = phaserPipelineMV <<^ mapFst cascadeParameterMultiValue
diff --git a/src/Synthesizer/LLVM/Filter/Butterworth.hs b/src/Synthesizer/LLVM/Filter/Butterworth.hs
--- a/src/Synthesizer/LLVM/Filter/Butterworth.hs
+++ b/src/Synthesizer/LLVM/Filter/Butterworth.hs
@@ -4,29 +4,28 @@
 {-# LANGUAGE FlexibleContexts #-}
 module Synthesizer.LLVM.Filter.Butterworth (
    parameter, parameterCausal, Cascade.ParameterValue,
-   Cascade.causal,  Cascade.causalPacked,
-   Cascade.causalP, Cascade.causalPackedP,
+   Cascade.causal, Cascade.causalPacked,
    Cascade.fixSize,
    ) where
 
 import qualified Synthesizer.LLVM.Filter.SecondOrderCascade as Cascade
 import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2
-import qualified Synthesizer.LLVM.Causal.ProcessPrivate as Causal
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as Sig
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Private as Sig
 
 import qualified Synthesizer.Plain.Filter.Recursive.Butterworth as Butterworth
 import Synthesizer.Plain.Filter.Recursive (Passband)
 import Synthesizer.Causal.Class (($<))
 
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Control as U
+import qualified LLVM.DSL.Expression as Expr
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Control as U
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core
-   (CodeGenFunction, Value, valueOf, constOf,
-    IsFloating, IsSized, SizeOf)
 
 import Data.Word (Word)
 
@@ -43,13 +42,12 @@
 
 
 parameterCausal ::
-   (Causal.C process,
-    Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a,
-    TypeNum.Natural n,
-    TypeNum.Positive (n :*: SizeOf a),
-    IsSized (Cascade.ParameterStruct n a)) =>
+   (TypeNum.Positive (n :*: LLVM.SizeOf (Marshal.Struct a)),
+    TypeNum.Natural (n :*: LLVM.UnknownSize),
+    TypeNum.Natural n, Trans.C a,
+    Marshal.C a, MultiValue.RationalConstant a, MultiValue.Transcendental a) =>
    Proxy n -> Passband ->
-   process (Value a, Value a) (Cascade.ParameterValue n a)
+   Causal.T (MultiValue.T a, MultiValue.T a) (Cascade.ParameterValue n a)
 parameterCausal n kind =
    Causal.map
       (\((psine, ps), (ratio, freq)) ->
@@ -58,12 +56,12 @@
    Sig.zipWith (curry return) Sig.alloca Sig.alloca
 
 parameter ::
-   (Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a,
-    TypeNum.Natural n,
-    TypeNum.Positive (n :*: SizeOf a),
-    IsSized (Cascade.ParameterStruct n a)) =>
-   Proxy n -> Passband -> Value a -> Value a ->
-   CodeGenFunction r (Cascade.ParameterValue n a)
+   (TypeNum.Positive (n :*: LLVM.SizeOf (Marshal.Struct a)),
+    TypeNum.Natural (n :*: LLVM.UnknownSize),
+    TypeNum.Natural n, Trans.C a,
+    Marshal.C a, MultiValue.RationalConstant a, MultiValue.Transcendental a) =>
+   Proxy n -> Passband -> MultiValue.T a -> MultiValue.T a ->
+   LLVM.CodeGenFunction r (Cascade.ParameterValue n a)
 parameter n kind ratio freq = do
    psine <- LLVM.malloc
    ps <- LLVM.malloc
@@ -73,29 +71,30 @@
    return pv
 
 parameterCore ::
-   (Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a,
-    TypeNum.Natural n,
-    TypeNum.Positive (n :*: SizeOf a),
-    IsSized (Cascade.ParameterStruct n a)) =>
+   (TypeNum.Positive (n :*: LLVM.SizeOf (Marshal.Struct a)),
+    TypeNum.Natural (n :*: LLVM.UnknownSize),
+    TypeNum.Natural n, Trans.C a,
+    Marshal.C a, MultiValue.RationalConstant a, MultiValue.Transcendental a) =>
    Proxy n -> Passband ->
-   Value (LLVM.Ptr (LLVM.Array n a)) ->
-   Value (LLVM.Ptr (Cascade.ParameterStruct n a)) ->
-   Value a -> Value a ->
-   CodeGenFunction r (Cascade.ParameterValue n a)
+   LLVM.Value (LLVM.Ptr (Marshal.Struct (MultiValue.Array n a))) ->
+   LLVM.Value (LLVM.Ptr (Cascade.ParameterStruct n a)) ->
+   MultiValue.T a -> MultiValue.T a ->
+   LLVM.CodeGenFunction r (Cascade.ParameterValue n a)
 parameterCore n kind psine ps ratio freq = do
    let order = 2 * TypeNum.integralFromProxy n
-   partialRatio <- Value.unlift1 (Butterworth.partialRatio order) ratio
-   let sines =
-          Cascade.constArray n $
-          map constOf $ Butterworth.makeSines order
-   LLVM.store sines psine
-   s <- LLVM.getElementPtr0 psine (valueOf (0::Word), ())
-   p <- LLVM.getElementPtr0 ps (valueOf (0::Word), ())
-   let len = valueOf $ (TypeNum.integralFromProxy n :: Word)
+   partialRatio <- Expr.unliftM1 (Butterworth.partialRatio order) ratio
+   let evalSines :: (Trans.C a) => mv a -> Int -> [a]
+       evalSines _ = Butterworth.makeSines
+   let sines = Cascade.constArray n $ evalSines freq order
+   Memory.store sines psine
+   s <- LLVM.getElementPtr0 psine (LLVM.valueOf (0::Word), ())
+   p <- LLVM.getElementPtr0 ps (LLVM.valueOf (0::Word), ())
+   let len = LLVM.valueOf (TypeNum.integralFromProxy n :: Word)
    _ <- U.arrayLoop len p s $ \ptri si -> do
-      sinw <- LLVM.load si
-      flip LLVM.store ptri =<<
-         Filt2.composeParameter =<<
-         Value.unlift3 (Butterworth.partialParameter kind) partialRatio sinw freq
+      sinw <- Memory.load si
+      flip Memory.store ptri =<<
+         Filt2.composeParameterMV =<<
+         Expr.unliftM3 (Butterworth.partialParameter kind)
+            partialRatio sinw freq
       A.advanceArrayElementPtr si
-   fmap Cascade.ParameterValue $ LLVM.load ps
+   fmap Cascade.ParameterValue $ Memory.load ps
diff --git a/src/Synthesizer/LLVM/Filter/Chebyshev.hs b/src/Synthesizer/LLVM/Filter/Chebyshev.hs
--- a/src/Synthesizer/LLVM/Filter/Chebyshev.hs
+++ b/src/Synthesizer/LLVM/Filter/Chebyshev.hs
@@ -6,38 +6,37 @@
    parameterCausalA, parameterCausalB,
    parameterA, parameterB, Cascade.ParameterValue,
    Cascade.causal,  Cascade.causalPacked,
-   Cascade.causalP, Cascade.causalPackedP,
    Cascade.fixSize,
    ) where
 
 import qualified Synthesizer.LLVM.Filter.SecondOrderCascade as Cascade
 import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2
-import qualified Synthesizer.LLVM.Causal.ProcessPrivate as Causal
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as Sig
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Private as Sig
 
 import qualified Synthesizer.Plain.Filter.Recursive.Chebyshev as Chebyshev
 import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core
 import Synthesizer.Plain.Filter.Recursive (Passband)
 import Synthesizer.Causal.Class (($<))
 
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Control as U
+import qualified LLVM.DSL.Expression as Expr
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Control as U
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core
-   (Value, valueOf, IsSized, SizeOf, IsFloating, CodeGenFunction)
 import Data.Word (Word)
 
-
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal.Number ((:*:))
 import Type.Base.Proxy (Proxy)
 
-import qualified Synthesizer.LLVM.Complex as ComplexL
+import qualified Synthesizer.LLVM.Complex as Complex
 
-import qualified Number.Complex as Complex
+import Control.Applicative (liftA2)
 
 import qualified Algebra.Transcendental as Trans
 
@@ -53,14 +52,12 @@
 because they use stack-based @alloca@ instead of @malloc@.
 -}
 parameterCausalA, parameterCausalB ::
-   (Causal.C process,
-    Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a,
-    TypeNum.Positive n, TypeNum.Natural n,
-    TypeNum.Positive (n :*: SizeOf a),
-    IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize,
-    (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.Positive paramSize) =>
+   (TypeNum.Natural n, Trans.C a,
+    Marshal.C a, MultiValue.RationalConstant a, MultiValue.Transcendental a) =>
+   (TypeNum.Positive (n :*: LLVM.SizeOf (Marshal.Struct a)),
+    TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
    Proxy n -> Passband ->
-   process (Value a, Value a) (Cascade.ParameterValue n a)
+   Causal.T (MultiValue.T a, MultiValue.T a) (Cascade.ParameterValue n a)
 parameterCausalA n kind =
    Causal.map
       (\((psine, ps), (ratio, freq)) ->
@@ -79,18 +76,17 @@
    allocaArrays
 
 allocaArrays ::
-   (Sig.C signal, IsSized a, IsSized b) =>
-   signal (Value (LLVM.Ptr a), Value (LLVM.Ptr b))
-allocaArrays = Sig.zipWith (curry return) Sig.alloca Sig.alloca
+   (LLVM.IsSized a, LLVM.IsSized b) =>
+   Sig.T (LLVM.Value (LLVM.Ptr a), LLVM.Value (LLVM.Ptr b))
+allocaArrays = liftA2 (,) Sig.alloca Sig.alloca
 
 parameterA, parameterB ::
-   (Trans.C a, SoV.TranscendentalConstant a, IsFloating a, IsSized a,
-    TypeNum.Positive n, TypeNum.Natural n,
-    TypeNum.Positive (n :*: SizeOf a),
-    IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize,
-    (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.Positive paramSize) =>
-   Proxy n -> Passband -> Value a -> Value a ->
-   CodeGenFunction r (Cascade.ParameterValue n a)
+   (TypeNum.Natural n, Trans.C a,
+    Marshal.C a, MultiValue.RationalConstant a, MultiValue.Transcendental a) =>
+   (TypeNum.Positive (n :*: LLVM.SizeOf (Marshal.Struct a)),
+    TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
+   Proxy n -> Passband -> MultiValue.T a -> MultiValue.T a ->
+   LLVM.CodeGenFunction r (Cascade.ParameterValue n a)
 parameterA n kind ratio freq =
    withArrays $ \psine ps ->
       fmap Cascade.ParameterValue $
@@ -104,8 +100,9 @@
 
 withArrays ::
    (LLVM.IsSized a, LLVM.IsSized b) =>
-   (Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> CodeGenFunction r c) ->
-   CodeGenFunction r c
+   (LLVM.Value (LLVM.Ptr a) -> LLVM.Value (LLVM.Ptr b) ->
+    LLVM.CodeGenFunction r c) ->
+   LLVM.CodeGenFunction r c
 withArrays act = do
    psine <- LLVM.malloc
    ps <- LLVM.malloc
@@ -117,52 +114,43 @@
 
 -- | adjust amplification of the first filter
 adjustAmplitude ::
-   (LLVM.IsArithmetic a, IsSized a, SoV.IntegerConstant a,
-    Filt2.ParameterStruct a ~ filt2, TypeNum.Natural n) =>
-   Value a -> Value (LLVM.Array n filt2) ->
-   CodeGenFunction r (Value (LLVM.Array n filt2))
-adjustAmplitude ratio pv = do
-   filt0 <-
-      Filt2.decomposeParameter =<<
-      LLVM.extractvalue pv (0::Word)
-   flip (LLVM.insertvalue pv) (0::Word) =<<
-      Filt2.composeParameter =<<
-      Value.flatten
-         (Filt2Core.amplify (Value.constantValue ratio) (Value.unfold filt0))
-
+   (TypeNum.Natural n, Filt2.Parameter a ~ filt2,
+    Marshal.C a, MultiValue.IntegerConstant a, MultiValue.PseudoRing a) =>
+   MultiValue.T a -> MultiValue.T (MultiValue.Array n filt2) ->
+   LLVM.CodeGenFunction r (MultiValue.T (MultiValue.Array n filt2))
+adjustAmplitude ratio (MultiValue.Cons pv) = do
+   filt0 <- Filt2.decomposeParameterMV =<< LLVM.extractvalue pv (0::Word)
+   fmap MultiValue.Cons $
+      flip (LLVM.insertvalue pv) (0::Word) =<<
+      Filt2.composeParameterMV =<<
+      Expr.unliftM2 Filt2Core.amplify ratio filt0
 
 parameter ::
-   (Trans.C a, SoV.RationalConstant a, IsFloating a, IsSized a,
-    Value.T (Value a) ~ av,
-    TypeNum.Positive n, TypeNum.Natural n,
-    TypeNum.Positive (n :*: SizeOf a),
-    IsSized (Cascade.ParameterStruct n a), SizeOf (Cascade.ParameterStruct n a) ~ paramSize,
-    (n :*: LLVM.UnknownSize) ~ paramSize, TypeNum.Positive paramSize) =>
-   (Passband -> Int -> av -> Complex.T av -> av -> Filt2Core.Parameter av) ->
+   (TypeNum.Positive (n :*: LLVM.SizeOf (Marshal.Struct a)),
+    TypeNum.Positive (n :*: LLVM.UnknownSize),
+    TypeNum.Natural n, Trans.C a,
+    Marshal.C a, MultiValue.RationalConstant a, MultiValue.Transcendental a,
+    Expr.Exp a ~ ae) =>
+   (Passband -> Int -> ae -> Complex.T ae -> ae -> Filt2Core.Parameter ae) ->
    Proxy n -> Passband ->
-   Value (LLVM.Ptr (LLVM.Array n (ComplexL.Struct a))) ->
-   Value (LLVM.Ptr (Cascade.ParameterStruct n a)) ->
-   Value a -> Value a ->
-   CodeGenFunction r (Value (Cascade.ParameterStruct n a))
+   LLVM.Value (LLVM.Ptr (Marshal.Struct (MultiValue.Array n (Complex.T a)))) ->
+   LLVM.Value (LLVM.Ptr (Cascade.ParameterStruct n a)) ->
+   MultiValue.T a -> MultiValue.T a ->
+   LLVM.CodeGenFunction r (MultiValue.T (Cascade.Parameter n a))
 parameter partialParameter n kind psine ps ratio freq = do
    let order = TypeNum.integralFromProxy n
-   let sines =
-          Cascade.constArray n $
-          map ComplexL.constOf $
-          Chebyshev.makeCirclePoints order
-   LLVM.store sines psine
-   s <- LLVM.getElementPtr0 psine (valueOf (0::Word), ())
-   p <- LLVM.getElementPtr0 ps (valueOf (0::Word), ())
-   let len = valueOf $ (TypeNum.integralFromProxy n :: Word)
+   let evalSines :: (Trans.C a) => mv a -> Int -> [Complex.T a]
+       evalSines _ = Chebyshev.makeCirclePoints
+   let sines = Cascade.constArray n $ evalSines freq order
+   Memory.store sines psine
+   s <- LLVM.getElementPtr0 psine (LLVM.valueOf (0::Word), ())
+   p <- LLVM.getElementPtr0 ps (LLVM.valueOf (0::Word), ())
+   let len = LLVM.valueOf (TypeNum.integralFromProxy n :: Word)
    _ <- U.arrayLoop len p s $ \ptri si -> do
-      c <- LLVM.load si
-      flip LLVM.store ptri =<<
-         Filt2.composeParameter =<<
-         Value.flatten
-            (partialParameter kind order
-               (Value.constantValue ratio)
-               (ComplexL.unfold c)
-               (Value.constantValue freq))
+      c <- Memory.load si
+      flip Memory.store ptri =<<
+         Filt2.composeParameterMV =<<
+         Expr.unliftM3 (partialParameter kind order) ratio c freq
       A.advanceArrayElementPtr si
 
-   LLVM.load ps
+   Memory.load ps
diff --git a/src/Synthesizer/LLVM/Filter/ComplexFirstOrder.hs b/src/Synthesizer/LLVM/Filter/ComplexFirstOrder.hs
--- a/src/Synthesizer/LLVM/Filter/ComplexFirstOrder.hs
+++ b/src/Synthesizer/LLVM/Filter/ComplexFirstOrder.hs
@@ -1,17 +1,20 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 module Synthesizer.LLVM.Filter.ComplexFirstOrder (
-   Parameter, parameter,
-   causal, causalP,
+   Parameter(Parameter), parameter, causal,
+   parameterCode, causalExp,
    ) where
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Causal.Process as CausalExp
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Value as Value
 
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 import qualified Synthesizer.LLVM.Complex as Complex
 
+import qualified LLVM.DSL.Expression as Expr
+
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Tuple as Tuple
@@ -27,6 +30,9 @@
 import qualified Data.Traversable as Trav
 import qualified Data.Foldable as Fold
 
+import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Ring as Ring
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -91,25 +97,39 @@
    flattenCode = Value.flattenCodeTraversable
    unfoldCode = Value.unfoldCodeTraversable
 
+instance
+   (Expr.Aggregate e mv) =>
+      Expr.Aggregate (Parameter e) (Parameter mv) where
+   type MultiValuesOf (Parameter e) = Parameter (Expr.MultiValuesOf e)
+   type ExpressionsOf (Parameter mv) = Parameter (Expr.ExpressionsOf mv)
+   bundle = Trav.traverse Expr.bundle
+   dissect = fmap Expr.dissect
 
-parameter, _parameter ::
+
+parameterCode, _parameterCode ::
    (A.Transcendental a, A.RationalConstant a) =>
    a -> a -> CodeGenFunction r (Parameter a)
-parameter reson freq =
+parameterCode reson freq =
    let amp = recip $ Value.unfold reson
    in  Value.flatten $ Parameter amp $
        Complex.scale (1-amp) $ Complex.cis $
-       Value.unfold freq * Value.twoPi
+       Value.unfold freq * Value.tau
 
-_parameter reson freq = do
+_parameterCode reson freq = do
    amp <- A.fdiv A.one reson
    k   <- A.sub  A.one amp
-   w  <- A.mul freq =<< Value.decons Value.twoPi
+   w  <- A.mul freq =<< Value.decons Value.tau
    kr <- A.mul k =<< A.cos w
    ki <- A.mul k =<< A.sin w
    return (Parameter amp (kr Complex.+: ki))
 
+parameter :: (Trans.C a) => a -> a -> Parameter a
+parameter reson freq =
+   let amp = recip reson
+   in Parameter amp $
+      Complex.scale (1-amp) $ Complex.cis $ freq * 2*pi
 
+
 {-
 Synthesizer.Plain.Filter.Recursive.FirstOrderComplex.step
 cannot be used directly, because Filt1C has complex amplitude
@@ -120,15 +140,12 @@
    Complex.T a ->
    CodeGenFunction r (Stereo.T a, Complex.T a)
 next inp state =
-   let stereoFromComplex ::
-          Complex.T a -> Complex.T (Value.T a) ->
-          Stereo.T (Value.T a)
-       stereoFromComplex _ c =
-          Stereo.cons (Complex.real c) (Complex.imag c)
+   let stereoFromComplexVal :: Complex.T (Value.T a) -> Stereo.T (Value.T a)
+       stereoFromComplexVal = stereoFromComplex
        (Parameter amp k, x) = Value.unfold inp
        xc = Stereo.left x  Complex.+:  Stereo.right x
        y = Complex.scale amp xc + k * Value.unfold state
-   in  Value.flatten (stereoFromComplex state y, y)
+   in  Value.flatten (stereoFromComplexVal y, y)
 
 _next (Parameter amp k, x) s = do
    let kr = Complex.real k
@@ -151,18 +168,27 @@
    return (A.zero Complex.+: A.zero)
 
 causal ::
-   (Causal.C process, A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
-   process
+   (A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
+   Causal.T
       (Parameter a, Stereo.T a)
       (Stereo.T a)
 causal =
    Causal.mapAccum next start
 
-{-# DEPRECATED causalP "use causal instead" #-}
-causalP ::
-   (A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
-   CausalP.T p
-      (Parameter a, Stereo.T a)
-      (Stereo.T a)
-causalP =
-   CausalP.mapAccumSimple next start
+
+stereoFromComplex :: Complex.T a -> Stereo.T a
+stereoFromComplex c = Stereo.cons (Complex.real c) (Complex.imag c)
+
+nextPlain ::
+   (Ring.C a) =>
+   (Parameter a, Stereo.T a) -> Complex.T a -> (Stereo.T a, Complex.T a)
+nextPlain (Parameter amp k, x) state =
+   let xc = Stereo.left x  Complex.+:  Stereo.right x
+       y = Complex.scale amp xc + k * state
+   in (stereoFromComplex y, y)
+
+causalExp ::
+   (Ring.C ae, Expr.Aggregate ae a, Memory.C a) =>
+   CausalExp.T (Parameter a, Stereo.T a) (Stereo.T a)
+causalExp =
+   CausalExp.mapAccum nextPlain zero
diff --git a/src/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hs b/src/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hs
--- a/src/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hs
+++ b/src/Synthesizer/LLVM/Filter/ComplexFirstOrderPacked.hs
@@ -2,150 +2,136 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE Rank2Types #-}
 module Synthesizer.LLVM.Filter.ComplexFirstOrderPacked (
-   Parameter, parameter,
-   causal, causalP,
+   Parameter(Parameter), parameterPlain, parameter, causal,
+   ParameterMV,
    ) where
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Filter.ComplexFirstOrder as ComplexFilter
 
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp(Exp))
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Tuple as Tuple
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core
-   (Value, valueOf, Struct,
-    IsPrimitive, IsFloating, IsSized,
-    Vector, insertelement,
-    CodeGenFunction)
 
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal (D4, d0, d1, (:*:))
+import Type.Data.Num.Decimal (D3, d0, d1)
 
 import Control.Applicative (liftA2)
 
+import qualified Algebra.Transcendental as Trans
+
+import qualified Number.Complex as Complex
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
 
--- the pair should also be replaced by a Vector
-data Parameter a =
-   Parameter (Value (Vector D4 a)) (Value (Vector D4 a))
+data Parameter a = Parameter (LLVM.Vector D3 a) (LLVM.Vector D3 a)
 
-instance IsPrimitive a => Tuple.Phi (Parameter a) where
-   phi bb (Parameter r i) = do
+data ParameterMV a = ParameterMV (MultiVector.T D3 a) (MultiVector.T D3 a)
+
+instance (MultiVector.C a) => Tuple.Phi (ParameterMV a) where
+   phi bb (ParameterMV r i) = do
       r' <- Tuple.phi bb r
       i' <- Tuple.phi bb i
-      return (Parameter r' i')
+      return (ParameterMV r' i')
    addPhi bb
-        (Parameter r i)
-        (Parameter r' i') = do
+        (ParameterMV r i)
+        (ParameterMV r' i') = do
       Tuple.addPhi bb r r'
       Tuple.addPhi bb i i'
 
-instance IsPrimitive a => Tuple.Undefined (Parameter a) where
-   undef = Parameter Tuple.undef Tuple.undef
+instance (MultiVector.C a) => Tuple.Undefined (ParameterMV a) where
+   undef = ParameterMV Tuple.undef Tuple.undef
 
 
-type ParameterStruct a = Struct (Vector D4 a, (Vector D4 a, ()))
+type ParameterStruct a = Marshal.Struct (LLVM.Vector D3 a, LLVM.Vector D3 a)
 
 parameterMemory ::
-   (IsPrimitive a, IsSized a,
-    TypeNum.Positive (TypeNum.D4 :*: LLVM.SizeOf a)) =>
-   Memory.Record r (ParameterStruct a) (Parameter a)
+   (Marshal.Vector D3 a) =>
+   Memory.Record r (ParameterStruct a) (ParameterMV a)
 parameterMemory =
-   liftA2 Parameter
-      (Memory.element (\(Parameter kr _) -> kr) d0)
-      (Memory.element (\(Parameter _ ki) -> ki) d1)
-
-{-
-The complicated Add constraints are caused by the IsType superclass of Memory.
-
-instance (IsPrimitive l, IsSized (Vector D4 l) ss) =>
-      Memory.C (Parameter l) (Struct (Vector D4 l, (Vector D4 l, ()))) where
+   liftA2 ParameterMV
+      (Memory.element (\(ParameterMV kr _) -> kr) d0)
+      (Memory.element (\(ParameterMV _ ki) -> ki) d1)
 
-Mul constraint seems to be not enough, GHC urges to give constraints in terms of Add
-instance (IsPrimitive l, IsSized l s, Mul D4 s ss, Sets.Pos ss) =>
-      Memory.C (Parameter l) (Struct (Vector D4 l, (Vector D4 l, ()))) where
--}
-instance
-   (IsPrimitive a, IsSized a,
-    TypeNum.Positive (TypeNum.D4 :*: LLVM.SizeOf a)) =>
-      Memory.C (Parameter a) where
-   type Struct (Parameter a) = ParameterStruct a
+instance (Marshal.Vector D3 a) => Memory.C (ParameterMV a) where
+   type Struct (ParameterMV a) = ParameterStruct a
    load = Memory.loadRecord parameterMemory
    store = Memory.storeRecord parameterMemory
    decompose = Memory.decomposeRecord parameterMemory
    compose = Memory.composeRecord parameterMemory
 
-parameter ::
-   (SoV.TranscendentalConstant a, IsFloating a, IsPrimitive a) =>
-   Value a -> Value a -> CodeGenFunction r (Parameter a)
-parameter reson freq = do
-   amp <- A.fdiv A.one reson
-   k   <- A.sub  A.one amp
-   w  <- A.mul freq =<< Value.decons Value.twoPi
-   kr <- A.mul k =<< A.cos w
-   ki <- A.mul k =<< A.sin w
 
-   kin <- A.neg ki
-   kvr <- Vector.assemble [kr,kin,amp, A.zero]
-   kvi <- Vector.assemble [ki,kr, amp, A.zero]
-   return (Parameter kvr kvi)
+data ParameterExp a =
+   ParameterExp (forall r. LLVM.CodeGenFunction r (ParameterMV a))
 
+instance Expr.Aggregate (ParameterExp a) (ParameterMV a) where
+   type MultiValuesOf (ParameterExp a) = ParameterMV a
+   type ExpressionsOf (ParameterMV a) = ParameterExp a
+   dissect x = ParameterExp (return x)
+   bundle (ParameterExp code) = code
 
-type State a = Vector D4 a
 
-{-
-The handling of Vector D2 Float in LLVM-2.5 and LLVM-2.6 is at least unexpected.
-Because of compatibility reasons, LLVM chooses MMX registers
-which requires to call EMMS occasionally.
-Thus I choose Vector D4 for Float computations.
-Actually, I have now rearranged the data
-such that we can make use of SSE4's dot product operation.
-This would even require a vector of size 3.
--}
+parameterPlain :: (Trans.C a) => a -> a -> Parameter a
+parameterPlain reson freq =
+   let (ComplexFilter.Parameter amp k) = ComplexFilter.parameter reson freq
+       kr = Complex.real k
+       ki = Complex.imag k
+   in Parameter
+         (LLVM.consVector kr (-ki) amp)
+         (LLVM.consVector ki   kr  amp)
+
+parameter ::
+   (MultiVector.Transcendental a, MultiVector.RationalConstant a) =>
+   Exp a -> Exp a -> ParameterExp a
+parameter (Exp reson) (Exp freq) =
+   ParameterExp (do
+      r <- reson
+      f <- freq
+      ~(ComplexFilter.Parameter amp k) <- ComplexFilter.parameterCode r f
+      let kr = Complex.real k
+      let ki = Complex.imag k
+      kin <- A.neg ki
+      liftA2 ParameterMV
+         (MultiVector.assembleFromVector $ LLVM.consVector kr kin amp)
+         (MultiVector.assembleFromVector $ LLVM.consVector ki kr  amp))
+
+
+type State a = MultiVector.T D3 a
+
 next ::
-   (Vector.Arithmetic a) =>
-   (Parameter a, Stereo.T (Value a)) ->
-   Value (State a) ->
-   CodeGenFunction r (Stereo.T (Value a), (Value (State a)))
-next (Parameter kr ki, x) s = do
-   sr <- insertelement s (Stereo.left  x) (valueOf 2)
-   yr <- Vector.dotProduct kr sr
+   (MultiVector.PseudoRing a) =>
+   (ParameterMV a, Stereo.T (MultiValue.T a)) ->
+   State a -> LLVM.CodeGenFunction r (Stereo.T (MultiValue.T a), State a)
+next (ParameterMV kr ki, x) s = do
+   let two = LLVM.valueOf 2
+   sr <- MultiVector.insert two (Stereo.left  x) s
+   yr <- MultiVector.dotProduct kr sr
 
-   si <- insertelement s (Stereo.right x) (valueOf 2)
-   yi <- Vector.dotProduct ki si
+   si <- MultiVector.insert two (Stereo.right x) s
+   yi <- MultiVector.dotProduct ki si
 
-   sv <- Vector.assemble [yr,yi]
+   sv <- MultiVector.assembleFromVector $ LLVM.consVector yr yi Tuple.undef
    return (Stereo.cons yr yi, sv)
 
-start ::
-   (Vector.Arithmetic a) =>
-   CodeGenFunction r (Value (State a))
-start = return A.zero
-
 causal ::
-   (Causal.C process, Vector.Arithmetic a, Memory.C (Value (State a))) =>
-   process
-      (Parameter a, Stereo.T (Value a))
-      (Stereo.T (Value a))
-causal =
-   Causal.mapAccum next start
-
-{-# DEPRECATED causalP "use causal instead" #-}
-causalP ::
-   (Vector.Arithmetic a, Memory.C (Value (State a))) =>
-   CausalP.T p
-      (Parameter a, Stereo.T (Value a))
-      (Stereo.T (Value a))
-causalP =
-   CausalP.mapAccumSimple next start
+   (Marshal.Vector n a, n ~ D3, MultiVector.PseudoRing a) =>
+   Causal.T
+      (ParameterMV a, Stereo.T (MultiValue.T a))
+      (Stereo.T (MultiValue.T a))
+causal = Causal.mapAccum next (return A.zero)
diff --git a/src/Synthesizer/LLVM/Filter/FirstOrder.hs b/src/Synthesizer/LLVM/Filter/FirstOrder.hs
--- a/src/Synthesizer/LLVM/Filter/FirstOrder.hs
+++ b/src/Synthesizer/LLVM/Filter/FirstOrder.hs
@@ -1,45 +1,40 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Synthesizer.LLVM.Filter.FirstOrder (
-   Result(Result,lowpass_,highpass_), Parameter, parameter,
+   Result(Result,lowpass_,highpass_), Parameter, FirstOrder.parameter,
    causal, lowpassCausal, highpassCausal,
    causalInit, lowpassCausalInit, highpassCausalInit,
-   causalInitPacked, lowpassCausalInitPacked, highpassCausalInitPacked,
    causalPacked, lowpassCausalPacked, highpassCausalPacked,
+   causalInitPacked, lowpassCausalInitPacked, highpassCausalInitPacked,
    causalRecursivePacked, -- for Allpass
-
-   causalP, lowpassCausalP, highpassCausalP,
-   causalInitP, lowpassCausalInitP, highpassCausalInitP,
-   causalPackedP, lowpassCausalPackedP, highpassCausalPackedP,
-   causalInitPackedP, lowpassCausalInitPackedP, highpassCausalInitPackedP,
-   causalRecursivePackedP, -- for Allpass
    ) where
 
 import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as FirstOrder
+import qualified Synthesizer.Plain.Modifier as Modifier
 import Synthesizer.Plain.Filter.Recursive.FirstOrder
           (Parameter(Parameter), Result(Result,lowpass_,highpass_))
 
-import qualified Synthesizer.Plain.Modifier as Modifier
-
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
 import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as SerialCode
 
-import qualified LLVM.DSL.Parameter as Param
+import qualified LLVM.DSL.Expression as Expr
 
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
 
 import qualified LLVM.Core as LLVM
 
 import Control.Arrow (arr, (&&&), (<<<))
-import Control.Monad (liftM2, foldM)
+import Control.Monad (foldM)
+import Control.Applicative (liftA2)
 
+import qualified Algebra.Module as Module
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -58,143 +53,70 @@
    decompose = Memory.decomposeNewtype Parameter
    compose = Memory.composeNewtype (\(Parameter k) -> k)
 
-instance (Marshal.C a) => Marshal.C (Parameter a) where
-   pack (Parameter k) = Marshal.pack k
-   unpack = Parameter . Marshal.unpack
 
-instance (Storable.C a) => Storable.C (Parameter a) where
-   load = Storable.loadNewtype Parameter Parameter
-   store = Storable.storeNewtype Parameter (\(Parameter k) -> k)
-
-instance (Value.Flatten a) => Value.Flatten (Parameter a) where
-   type Registers (Parameter a) = Parameter (Value.Registers a)
-   flattenCode = Value.flattenCodeTraversable
-   unfoldCode = Value.unfoldCodeTraversable
-
-instance (Value.Flatten a) => Value.Flatten (Result a) where
-   type Registers (Result a) = Result (Value.Registers a)
-   flattenCode = Value.flattenCodeTraversable
-   unfoldCode = Value.unfoldCodeTraversable
-
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (Parameter a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
-
-instance LLVM.IsTuple a => LLVM.IsTuple (Parameter a) where
-   tupleDesc = Class.tupleDescFoldable
--}
-
-instance (Tuple.Value a) => Tuple.Value (Parameter a) where
-   type ValueOf (Parameter a) = Parameter (Tuple.ValueOf a)
-   valueOf = Tuple.valueOfFunctor
-
-
-parameter ::
-   (A.Transcendental a, A.RationalConstant a) =>
-   a -> LLVM.CodeGenFunction r (Parameter a)
-parameter = Value.unlift1 FirstOrder.parameter
+instance
+   (Expr.Aggregate e mv) =>
+      Expr.Aggregate (Parameter e) (Parameter mv) where
+   type MultiValuesOf (Parameter e) = Parameter (Expr.MultiValuesOf e)
+   type ExpressionsOf (Parameter mv) = Parameter (Expr.ExpressionsOf mv)
+   bundle (Parameter p) = fmap Parameter $ Expr.bundle p
+   dissect (Parameter p) = Parameter $ Expr.dissect p
 
 
-modifier ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-   Modifier.Simple
-      (Value.T v)
-      (Parameter (Value.T a))
-      (Value.T v) (Result (Value.T v))
-modifier = FirstOrder.modifier
-
-lowpassModifier, highpassModifier ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-   Modifier.Simple
---      (FirstOrder.State (Value.T v))
-      (Value.T v)
-      (Parameter (Value.T a))
-      (Value.T v) (Value.T v)
-lowpassModifier  = FirstOrder.lowpassModifier
-highpassModifier = FirstOrder.highpassModifier
+instance (Expr.Aggregate e mv) => Expr.Aggregate (Result e) (Result mv) where
+   type MultiValuesOf (Result e) = Result (Expr.MultiValuesOf e)
+   type ExpressionsOf (Result mv) = Result (Expr.ExpressionsOf mv)
+   bundle (Result f k) = liftA2 Result (Expr.bundle f) (Expr.bundle k)
+   dissect (Result f k) = Result (Expr.dissect f) (Expr.dissect k)
 
 causal ::
-   (Causal.C process,
-    A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   process (Parameter a, v) (Result v)
-causal = Causal.fromModifier modifier
+   (Expr.Aggregate ae a, Module.C ae ve,
+    Expr.Aggregate ve v, Memory.C v) =>
+   Causal.T (Parameter a, v) (Result v)
+causal = Causal.fromModifier FirstOrder.modifier
 
 lowpassCausal, highpassCausal ::
-   (Causal.C process,
-    A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   process (Parameter a, v) v
-lowpassCausal  = CausalP.fromModifier lowpassModifier
-highpassCausal = CausalP.fromModifier highpassModifier
+   (Expr.Aggregate ae a, Module.C ae ve,
+    Expr.Aggregate ve v, Memory.C v) =>
+   Causal.T (Parameter a, v) v
+lowpassCausal  = Causal.fromModifier FirstOrder.lowpassModifier
+highpassCausal = Causal.fromModifier FirstOrder.highpassModifier
 
 
-modifierInit ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-   Modifier.Initialized
-      (Value.T v) (Value.T v)
-      (Parameter (Value.T a))
-      (Value.T v) (Result (Value.T v))
-modifierInit = FirstOrder.modifierInit
-
-lowpassModifierInit, highpassModifierInit ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-   Modifier.Initialized
-      (Value.T v) (Value.T v)
-      (Parameter (Value.T a))
-      (Value.T v) (Value.T v)
-lowpassModifierInit  = FirstOrder.lowpassModifierInit
-highpassModifierInit = FirstOrder.highpassModifierInit
-
 causalInit ::
-   (Causal.C process,
-    A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   v -> process (Parameter a, v) (Result v)
+   (Expr.Aggregate ae a, Memory.C a, Module.C ae ve,
+    Expr.Aggregate ve v, Memory.C v) =>
+   ve -> Causal.T (Parameter a, v) (Result v)
 causalInit =
-   Causal.fromModifier . Modifier.initialize modifierInit . Value.unfold
+   Causal.fromModifier . Modifier.initialize FirstOrder.modifierInit
 
 lowpassCausalInit, highpassCausalInit ::
-   (Causal.C process,
-    A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   v -> process (Parameter a, v) v
+   (Expr.Aggregate ae a, Memory.C a, Module.C ae ve,
+    Expr.Aggregate ve v, Memory.C v) =>
+   ve -> Causal.T (Parameter a, v) v
 lowpassCausalInit =
-   CausalP.fromModifier .
-   Modifier.initialize lowpassModifierInit . Value.unfold
+   Causal.fromModifier . Modifier.initialize FirstOrder.lowpassModifierInit
 highpassCausalInit =
-   CausalP.fromModifier .
-   Modifier.initialize highpassModifierInit . Value.unfold
+   Causal.fromModifier . Modifier.initialize FirstOrder.highpassModifierInit
 
 
 lowpassCausalPacked, highpassCausalPacked, causalRecursivePacked,
       preampPacked ::
-   (Causal.C process,
-    Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   process (Parameter a, v) v
+   (SerialCode.Write v, SerialCode.Element v ~ a,
+    A.PseudoRing v, A.IntegerConstant v,
+    A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
+   Causal.T (Parameter a, v) v
 highpassCausalPacked =
-   Causal.zipWith A.sub <<< arr snd &&& lowpassCausalPacked
+   CausalPriv.zipWith A.sub <<< arr snd &&& lowpassCausalPacked
 lowpassCausalPacked =
-   causalRecursivePacked <<< (arr fst &&& preampPacked)
+   causalRecursivePacked <<< arr fst &&& preampPacked
 
 causalRecursivePacked =
-   causalRecursiveInitPacked A.zero
-
-lowpassCausalInitPacked, highpassCausalInitPacked, causalRecursiveInitPacked ::
-   (Causal.C process,
-    A.PseudoRing v, Serial.C v, Serial.Element v ~ a,
-    A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
-   a -> process (Parameter a, v) v
-causalRecursiveInitPacked a =
-   Causal.mapAccum causalRecursivePackedStep (return a)
-
-highpassCausalInitPacked a =
-   Causal.zipWith A.sub <<< arr snd &&& lowpassCausalInitPacked a
-lowpassCausalInitPacked a =
-   causalRecursiveInitPacked a <<< (arr fst &&& preampPacked)
+   CausalPriv.mapAccum causalRecursivePackedStep (return A.zero)
 
 preampPacked =
-   Causal.map
-      (\(Parameter k, x) ->
-         A.mul x =<< Serial.upsample =<< A.sub (A.fromInteger' 1) k)
+   CausalPriv.map
+      (\(Parameter k, x) -> A.mul x =<< SerialCode.upsample =<< A.sub A.one k)
 
 
 
@@ -213,41 +135,24 @@
 f2x = f1x + k^2 * f1x->2
 -}
 causalRecursivePackedStep ::
-   (A.PseudoRing v, Serial.C v, Serial.Element v ~ a, A.PseudoRing a) =>
+   (SerialCode.Write v, SerialCode.Element v ~ a,
+    A.PseudoRing v, A.IntegerConstant v, A.PseudoRing a) =>
    (Parameter a, v) -> a -> LLVM.CodeGenFunction r (v,a)
-causalRecursivePackedStep =
-      \(Parameter k, xk0) y1 -> do
-         y1k <- A.mul k y1
-         xk1 <- Serial.modify A.zero (A.add y1k) xk0
-         let size = Serial.size xk0
-         kv <- Serial.upsample k
-         xk2 <-
-            fmap fst $
-            foldM
-               (\(y,k0) d ->
-                  liftM2 (,)
-                     (A.add y =<<
-                      Serial.shiftUpMultiZero d =<<
-                      A.mul y k0)
-                     (A.mul k0 k0))
-               (xk1,kv)
-               (takeWhile (< size) $ iterate (2*) 1)
-{- do replicate in the loop
-         xk2 <-
-            fmap fst $
-            foldM
-               (\(y,k0) d ->
-                  liftM2 (,)
-                     (A.add y =<<
-                      Serial.shiftUpMultiZero d =<<
-                      A.mul y =<<
-                      Serial.upsample k0)
-                     (A.mul k0 k0))
-               (xk1,k)
-               (takeWhile (< size) $ iterate (2*) 1)
--}
-         y0 <- Serial.extract (LLVM.valueOf $ fromIntegral $ size - 1) xk2
-         return (xk2, y0)
+causalRecursivePackedStep (Parameter k, xk0) y1 = do
+   y1k <- A.mul k y1
+   xk1 <- SerialCode.modify A.zero (A.add y1k) xk0
+   kv <- SerialCode.upsample k
+   xk2 <-
+      fmap fst $
+      foldM
+         (\(y,k0) d ->
+            liftA2 (,)
+               (A.add y =<< SerialCode.shiftUpMultiZero d =<< A.mul y k0)
+               (A.mul k0 k0))
+         (xk1,kv)
+         (takeWhile (< SerialCode.size xk0) $ iterate (2*) 1)
+   y0 <- SerialCode.last xk2
+   return (xk2, y0)
 
 {-
 We can also optimize filtering with time-varying filter parameter.
@@ -288,105 +193,41 @@
 -}
 
 
-
 addHighpass ::
-   (Causal.C process, A.Additive v) =>
-   process (param, v) v -> process (param, v) (Result v)
+   (A.Additive v) =>
+   Causal.T (param,v) v -> Causal.T (param,v) (Result v)
 addHighpass lowpass =
-{-
-Before we added sharing to Simple.Value,
-only this implementation allowed sharing
-and using CausalP.fromModifier did not.
--}
-   Causal.map (\(l,x) -> do
-      h <- A.sub x l
-      return (Result{lowpass_ = l, highpass_ = h}))
-    <<< (lowpass &&& arr snd)
+   CausalPriv.map
+      (\(l,x) -> do
+         h <- A.sub x l
+         return (Result{lowpass_ = l, highpass_ = h}))
+   <<<
+   lowpass &&& arr snd
 
 causalPacked ::
-   (Causal.C process,
-    Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   process (Parameter a, v) (Result v)
+   (SerialCode.Write v, SerialCode.Element v ~ a,
+    A.PseudoRing v, A.IntegerConstant v,
+    A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
+   Causal.T (Parameter a, v) (Result v)
 causalPacked = addHighpass lowpassCausalPacked
 
-causalInitPacked ::
-   (Causal.C process,
-    Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   a -> process (Parameter a, v) (Result v)
-causalInitPacked a = addHighpass (lowpassCausalInitPacked a)
 
-
-
-causalP ::
-   (A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   CausalP.T p (Parameter a, v) (Result v)
-causalP = addHighpass lowpassCausalP
-
-lowpassCausalP, highpassCausalP ::
-   (A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v, Memory.C v) =>
-   CausalP.T p (Parameter a, v) v
-lowpassCausalP  = lowpassCausal
-highpassCausalP = highpassCausal
-
-causalInitP ::
-   (A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v,
-    Marshal.C vh, Tuple.ValueOf vh ~ v) =>
-   Param.T p vh -> CausalP.T p (Parameter a, v) (Result v)
-causalInitP = CausalP.fromInitializedModifier modifierInit
-
-lowpassCausalInitP, highpassCausalInitP ::
-   (A.IntegerConstant a, a ~ A.Scalar v, A.PseudoModule v,
-    Marshal.C vh, Tuple.ValueOf vh ~ v) =>
-   Param.T p vh -> CausalP.T p (Parameter a, v) v
-lowpassCausalInitP = CausalP.fromInitializedModifier lowpassModifierInit
-highpassCausalInitP = CausalP.fromInitializedModifier highpassModifierInit
-
-lowpassCausalPackedP, highpassCausalPackedP, causalRecursivePackedP ::
-   (Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   CausalP.T p (Parameter a, v) v
-highpassCausalPackedP = highpassCausalPacked
-lowpassCausalPackedP = lowpassCausalPacked
-causalRecursivePackedP = causalRecursivePacked
-
-lowpassCausalInitPackedP, highpassCausalInitPackedP,
-      causalRecursiveInitPackedP ::
-   (A.PseudoRing v, Serial.C v, Serial.Element v ~ a,
-    A.PseudoRing a, A.IntegerConstant a,
-    Marshal.C ah, Tuple.ValueOf ah ~ a) =>
-   Param.T p ah -> CausalP.T p (Parameter a, v) v
-causalRecursiveInitPackedP a =
-   CausalP.mapAccum (\() -> causalRecursivePackedStep) return (return ()) a
-
-highpassCausalInitPackedP a =
-   Causal.zipWith A.sub <<< arr snd &&& lowpassCausalInitPackedP a
-lowpassCausalInitPackedP a =
-   causalRecursiveInitPackedP a <<< (arr fst &&& preampPacked)
-
-causalPackedP ::
-   (Serial.C v, Serial.Element v ~ a,
-    Memory.C a, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   CausalP.T p (Parameter a, v) (Result v)
-causalPackedP = causalPacked
-
-causalInitPackedP ::
-   (A.PseudoRing v, Serial.C v, Serial.Element v ~ a,
-    A.PseudoRing a, A.IntegerConstant a,
-    Marshal.C ah, Tuple.ValueOf ah ~ a) =>
-   Param.T p ah -> CausalP.T p (Parameter a, v) (Result v)
-causalInitPackedP a = addHighpass (lowpassCausalInitPackedP a)
+lowpassCausalInitPacked, highpassCausalInitPacked,
+      causalRecursiveInitPacked ::
+   (A.PseudoRing v, A.IntegerConstant v,
+    SerialCode.Write v, SerialCode.Element v ~ a,
+    Expr.Aggregate ae a, A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
+   ae -> Causal.T (Parameter a, v) v
+causalRecursiveInitPacked a =
+   CausalPriv.mapAccum causalRecursivePackedStep (Expr.bundle a)
 
+highpassCausalInitPacked a = arr snd - lowpassCausalInitPacked a
+lowpassCausalInitPacked a =
+   causalRecursiveInitPacked a <<< arr fst &&& preampPacked
 
-{-# DEPRECATED causalP                "use 'causal' instead" #-}
-{-# DEPRECATED lowpassCausalP         "use 'lowpassCausal' instead" #-}
-{-# DEPRECATED highpassCausalP        "use 'highpassCausal' instead" #-}
-{-# DEPRECATED causalPackedP          "use 'causalPacked' instead" #-}
-{-# DEPRECATED lowpassCausalPackedP   "use 'lowpassCausalPacked' instead" #-}
-{-# DEPRECATED highpassCausalPackedP  "use 'highpassCausalPacked' instead" #-}
-{-# DEPRECATED causalRecursivePackedP "use 'causalRecursivePacked' instead" #-}
+causalInitPacked ::
+   (A.PseudoRing v, A.IntegerConstant v,
+    SerialCode.Write v, SerialCode.Element v ~ a,
+    Expr.Aggregate ae a, A.PseudoRing a, A.IntegerConstant a, Memory.C a) =>
+   ae -> Causal.T (Parameter a, v) (Result v)
+causalInitPacked a = addHighpass (lowpassCausalInitPacked a)
diff --git a/src/Synthesizer/LLVM/Filter/Moog.hs b/src/Synthesizer/LLVM/Filter/Moog.hs
--- a/src/Synthesizer/LLVM/Filter/Moog.hs
+++ b/src/Synthesizer/LLVM/Filter/Moog.hs
@@ -1,33 +1,29 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE DeriveTraversable #-}
-module Synthesizer.LLVM.Filter.Moog
-   (Parameter, parameter,
-    causal, causalInit,
-    causalP, causalInitP,
+module Synthesizer.LLVM.Filter.Moog (
+   Parameter, parameter,
+   causal, causalInit,
    ) where
 
-import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1
+import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1 ()
 
 import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as FirstOrder
 import qualified Synthesizer.Plain.Filter.Recursive.Moog as Moog
 import Synthesizer.Plain.Filter.Recursive (Pole(..))
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
 import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Simple.Value as Value
 
-import qualified LLVM.DSL.Parameter as Param
+import qualified LLVM.DSL.Expression as Expr
 
 import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Tuple as Tuple
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction)
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal (d0, d1)
@@ -40,6 +36,8 @@
 import Control.Arrow (arr, (>>>), (&&&))
 import Control.Applicative (liftA2)
 
+import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Module as Module
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -62,33 +60,30 @@
    zero = Tuple.zeroPointed
 
 
-type ParameterStruct a = LLVM.Struct (a, (a, ()))
+type ParameterStruct a =
+   LLVM.Struct (Memory.Struct a, (Memory.Struct (FirstOrder.Parameter a), ()))
 
 parameterMemory ::
    (Memory.C a, TypeNum.Natural n) =>
-   Memory.Record r (ParameterStruct (Memory.Struct a)) (Parameter n a)
+   Memory.Record r (ParameterStruct a) (Parameter n a)
 parameterMemory =
    liftA2 (\f k -> Parameter (Moog.Parameter f k))
       (Memory.element (Moog.feedback     . getParam) d0)
       (Memory.element (Moog.lowpassParam . getParam) d1)
 
 instance
-      (Memory.C a, TypeNum.Natural n) =>
+   (Memory.C a, TypeNum.Natural n) =>
       Memory.C (Parameter n a) where
-   type Struct (Parameter n a) = ParameterStruct (Memory.Struct a)
+   type Struct (Parameter n a) = ParameterStruct a
    load = Memory.loadRecord parameterMemory
    store = Memory.storeRecord parameterMemory
    decompose = Memory.decomposeRecord parameterMemory
    compose = Memory.composeRecord parameterMemory
 
 
-instance (Value.Flatten a, TypeNum.Natural n) => Value.Flatten (Parameter n a) where
-   type Registers (Parameter n a) = Parameter n (Value.Registers a)
-   flattenCode = Value.flattenCodeTraversable
-   unfoldCode = Value.unfoldCodeTraversable
-
-
-instance (Vector.Simple v, TypeNum.Natural n) => Vector.Simple (Parameter n v) where
+instance
+   (Vector.Simple v, TypeNum.Natural n) =>
+      Vector.Simple (Parameter n v) where
    type Element (Parameter n v) = Parameter n (Vector.Element v)
    type Size (Parameter n v) = Vector.Size v
    shuffleMatch = Vector.shuffleMatchTraversable
@@ -99,81 +94,64 @@
 
 
 parameter ::
-   (A.Transcendental a, A.RationalConstant a, TypeNum.Natural n) =>
-   Proxy n -> a -> a ->
-   CodeGenFunction r (Parameter n a)
-parameter order =
-   Value.unlift2 $ \reson freq ->
-   Parameter $ Moog.parameter (TypeNum.integralFromProxy order) (Pole reson freq)
+   (TypeNum.Natural n, Trans.C a) =>
+   Proxy n -> a -> a -> Parameter n a
+parameter order reson freq =
+   Parameter $
+   Moog.parameter (TypeNum.integralFromProxy order) (Pole reson freq)
 
+instance
+   (n ~ m, Expr.Aggregate e mv) =>
+      Expr.Aggregate (Parameter n e) (Parameter m mv) where
+   type MultiValuesOf (Parameter n e) = Parameter n (Expr.MultiValuesOf e)
+   type ExpressionsOf (Parameter m mv) = Parameter m (Expr.ExpressionsOf mv)
+   bundle (Parameter (Moog.Parameter f k)) =
+      fmap Parameter $ liftA2 Moog.Parameter (Expr.bundle f) (Expr.bundle k)
+   dissect (Parameter (Moog.Parameter f k)) =
+      Parameter (Moog.Parameter (Expr.dissect f) (Expr.dissect k))
 
+
 merge ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-   (Parameter n a, v) -> v ->
-   CodeGenFunction r (FirstOrder.Parameter a, v)
-merge (Parameter (Moog.Parameter f k), x) y0 =
-   let c :: a -> Value.T a
-       c = Value.constantValue
-   in  Value.flatten (fmap c k, c x - c f *> c y0)
+   (Module.C a v) => (Parameter n a, v) -> v -> (FirstOrder.Parameter a, v)
+merge (Parameter (Moog.Parameter f k), x) y0 = (k, x - f *> y0)
 
-amplify ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-   Parameter n a ->
-   v ->
-   CodeGenFunction r v
-amplify =
-   Value.unlift2 $ \p y1 ->
-      case fmap (Moog.feedback . getParam) p of
-         f -> (1 + f) *> y1
+amplify :: (Module.C a v) => Parameter n a -> v -> v
+amplify p y1 = (1 + Moog.feedback (getParam p)) *> y1
 
 causal ::
-   (Causal.C process,
-    Memory.C v, A.PseudoModule v, A.Scalar v ~ a, A.IntegerConstant a,
-    TypeNum.Natural n) =>
-   process (Parameter n a, v) v
+   (TypeNum.Natural n, Memory.C v,
+    Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v) =>
+   Causal.T (Parameter n a, v) v
 causal =
    causalSize
-      (flip Causal.feedbackControlledZero (arr snd))
+      (flip (Causal.feedbackControlled zero) (arr snd))
       Proxy
 
-causalP ::
-   (Memory.C v, A.PseudoModule v, A.Scalar v ~ a, A.IntegerConstant a,
-    TypeNum.Natural n) =>
-   CausalP.T p (Parameter n a, v) v
-causalP = causal
 
-
-causalInit, causalInitP ::
-   (Marshal.C vh, Tuple.ValueOf vh ~ v,
-    A.PseudoModule v, A.Scalar v ~ a, A.IntegerConstant a,
-    TypeNum.Natural n) =>
-   Param.T p vh -> CausalP.T p (Parameter n a, v) v
-causalInit = causalInitP
-causalInitP initial =
-   let selectOutput :: Param.T p vh -> (b, Tuple.ValueOf vh) -> Tuple.ValueOf vh
-       selectOutput _ = snd
-   in  causalSize
-          (flip
-             (CausalP.feedbackControlled initial)
-             (arr $ selectOutput initial))
-          Proxy
+causalInit ::
+   (TypeNum.Natural n, Memory.C v,
+    Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v) =>
+   ve -> Causal.T (Parameter n a, v) v
+causalInit initial =
+   causalSize
+      (flip
+         (Causal.feedbackControlled initial)
+         (arr snd))
+      Proxy
 
 
 causalSize ::
-   (Causal.C process,
-    Memory.C v, A.PseudoModule v, A.Scalar v ~ a, A.IntegerConstant a,
-    TypeNum.Natural n) =>
-   (process ((Parameter n a, v), v) v ->
-    process (Parameter n a, v) v) ->
+   (TypeNum.Natural n, Memory.C v,
+    Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v) =>
+   (Causal.T ((Parameter n a, v), v) v ->
+    Causal.T (Parameter n a, v) v) ->
    Proxy n ->
-   process (Parameter n a, v) v
+   Causal.T (Parameter n a, v) v
 causalSize feedback n =
    let order = TypeNum.integralFromProxy n
    in  Arrow.arr fst &&&
        feedback
           (Causal.zipWith merge >>>
-           Causal.replicateControlled order Filt1.lowpassCausal)
+           Causal.replicateControlled order
+             (Causal.fromModifier FirstOrder.lowpassModifier))
         >>> Causal.zipWith amplify
-
-{-# DEPRECATED causalP     "use 'causal' instead" #-}
-{-# DEPRECATED causalInitP "use 'causalInit' instead" #-}
diff --git a/src/Synthesizer/LLVM/Filter/NonRecursive.hs b/src/Synthesizer/LLVM/Filter/NonRecursive.hs
--- a/src/Synthesizer/LLVM/Filter/NonRecursive.hs
+++ b/src/Synthesizer/LLVM/Filter/NonRecursive.hs
@@ -1,45 +1,44 @@
-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleContexts #-}
 module Synthesizer.LLVM.Filter.NonRecursive (
    convolve,
    convolvePacked,
    ) where
 
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate as CausalP
-import qualified Synthesizer.LLVM.CausalParameterized.RingBuffer as RingBuffer
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Causal.Private as CausalPriv
+import qualified Synthesizer.LLVM.Generator.Source as Source
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.RingBuffer as RingBuffer
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
 
-import qualified Synthesizer.LLVM.Storable.Vector as SVU
-import qualified Data.StorableVector as SV
+import qualified Synthesizer.Causal.Class as CausalClass
+import Synthesizer.Causal.Class (($<))
 
-import qualified LLVM.DSL.Parameter as Param
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
 
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Control as C
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Tuple as Tuple
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core (Value, valueOf, CodeGenFunction, IsSized, SizeOf)
 
 import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal.Number ((:*:))
 
-import Foreign.ForeignPtr (touchForeignPtr)
 import Foreign.Ptr (Ptr)
 import Data.Word (Word)
 
 import Control.Arrow ((<<<), (&&&))
 import Control.Monad (liftM2)
 
-import qualified Algebra.IntegralDomain as Integral
-
 import NumericPrelude.Numeric
 import NumericPrelude.Base
-
+import Prelude ()
 
 
 {-
@@ -47,86 +46,75 @@
 No Karatsuba, No Toom-Cook, No Fourier.
 -}
 convolve ::
-   (Storable.C a, Tuple.ValueOf a ~ al, Memory.C al, A.PseudoRing al) =>
-   Param.T p (SV.Vector a) -> CausalP.T p al al
+   (Storable.C a, Marshal.C a, MultiValue.PseudoRing a, MultiValue.T a ~ am) =>
+   Exp (Source.StorableVector a) -> Causal.T am am
 convolve mask =
-   let len = fmap SV.length mask
-   in  CausalP.zipWith scalarProduct
-         (fmap (fromIntegral :: Int -> Word) len)
-       <<<
-       RingBuffer.trackConst A.zero len &&& provideMask mask
+   let len = Source.storableVectorLength mask
+   in (CausalPriv.zipWith (\(MultiValue.Cons l) -> scalarProduct l)
+         $< Sig.constant len)
+      <<<
+      Causal.track Expr.zero len &&& provideMask mask
 
 convolvePacked ::
-   (TypeNum.Positive n, TypeNum.Positive (n :*: asize),
-    Storable.C a, Tuple.ValueOf a ~ Value al,
-    LLVM.IsArithmetic al, LLVM.IsPrimitive al, IsSized al, SizeOf al ~ asize) =>
-   Param.T p (SV.Vector a) ->
-   CausalP.T p (Serial.Value n al) (Serial.Value n al)
-convolvePacked mask =
-   Serial.withSize $ \vectorSize ->
-      let len = fmap SV.length mask
-      in  CausalP.zipWith scalarProductPacked
-             (fmap (fromIntegral :: Int -> Word) len)
-          <<<
-          RingBuffer.trackConst A.zero
-             (fmap (flip Integral.divUp vectorSize) len)
-          &&&
-          provideMask mask
+   (Marshal.Vector n a, MultiVector.PseudoRing a) =>
+   (Storable.C a, MultiValue.PseudoRing a, Serial.Value n a ~ v) =>
+   Exp (Source.StorableVector a) -> Causal.T v v
+convolvePacked = convolvePackedAux TypeNum.singleton
 
+convolvePackedAux ::
+   (Marshal.Vector n a, MultiVector.PseudoRing a) =>
+   (Storable.C a, MultiValue.PseudoRing a, Serial.Value n a ~ v) =>
+   TypeNum.Singleton n -> Exp (Source.StorableVector a) -> Causal.T v v
+convolvePackedAux vectorSize mask =
+   let len = Source.storableVectorLength mask
+   in (CausalPriv.zipWith (\(MultiValue.Cons l) -> scalarProductPacked l)
+         $< Sig.constant len)
+      <<<
+      Causal.track Expr.zero
+         (divUp (TypeNum.integralFromSingleton vectorSize) len)
+      &&&
+      provideMask mask
+
+divUp :: Exp Word -> Exp Word -> Exp Word
+divUp k n = Expr.idiv (n+(k-1)) k
+
 provideMask ::
-   (Storable.C a) => Param.T p (SV.Vector a) -> CausalP.T p x (Value (Ptr a))
+   (Storable.C a) =>
+   Exp (Source.StorableVector a) -> Causal.T x (LLVM.Value (Ptr a))
 provideMask mask =
-   CausalP.Cons
-      (\p () _x () -> return (p,()))
-      (return ())
-      return
-      (const $ const $ return ())
-      (\p ->
-         let (fp,ptr,_l) = SVU.unsafeToPointers $ Param.get mask p
-         in  return (fp, (ptr, ())))
-      -- keep the foreign ptr alive
-      touchForeignPtr
+   CausalClass.fromSignal $
+   fmap (\(MultiValue.Cons (ptr,_l)) -> ptr) $
+   Sig.constant mask
 
 
 scalarProduct ::
-   (Storable.C a, Tuple.ValueOf a ~ al, Memory.C al, A.PseudoRing al) =>
-   Value Word ->
-   RingBuffer.T al -> Value (Ptr a) ->
-   CodeGenFunction r al
-scalarProduct n rb mask =
+   (Storable.C a, Marshal.C a, MultiValue.T a ~ am, MultiValue.PseudoRing a) =>
+   LLVM.Value Word ->
+   (RingBuffer.T am, LLVM.Value (Ptr a)) ->
+   LLVM.CodeGenFunction r am
+scalarProduct n (rb,mask) =
    fmap snd $
    Storable.arrayLoop n mask (A.zero, A.zero) $ \ptr (k, s) -> do
       a <- RingBuffer.index k rb
       b <- Storable.load ptr
       liftM2 (,) (A.inc k) (A.add s =<< A.mul a b)
 
-_scalarProduct ::
-   (Storable.C a, IsSized a,
-    Tuple.ValueOf a ~ Value a, LLVM.IsArithmetic a) =>
-   Value Word ->
-   RingBuffer.T (Value a) -> Value (Ptr a) ->
-   CodeGenFunction r (Value a)
-_scalarProduct = scalarProduct
 
-
 scalarProductPacked ::
-   (Storable.C a,
-    Tuple.ValueOf a ~ Value al, LLVM.IsArithmetic al,
-    LLVM.IsPrimitive al, IsSized al, SizeOf al ~ asize,
-    TypeNum.Positive n, TypeNum.Positive (n :*: asize)) =>
-   Value Word ->
-   RingBuffer.T (Serial.Value n al) -> Value (Ptr a) ->
-   CodeGenFunction r (Serial.Value n al)
-scalarProductPacked n0 rb mask0 = do
+   (Storable.C a, Marshal.Vector n a, MultiVector.PseudoRing a) =>
+   LLVM.Value Word ->
+   (RingBuffer.T (Serial.Value n a), LLVM.Value (Ptr a)) ->
+   LLVM.CodeGenFunction r (Serial.Value n a)
+scalarProductPacked n0 (rb,mask0) = do
    (ax, rx) <- readSerialStart rb
    bx <- Storable.load mask0
-   sx <- A.scale bx ax
+   sx <- Serial.scale bx ax
    n1 <- A.dec n0
    mask1 <- Storable.incrementPtr mask0
    fmap snd $ Storable.arrayLoop n1 mask1 (rx, sx) $ \ptr (r1, s1) -> do
       (a,r2) <- readSerialNext rb r1
       b <- Storable.load ptr
-      fmap ((,) r2) (A.add s1 =<< A.scale b a)
+      fmap ((,) r2) (A.add s1 =<< Serial.scale b a)
 
 
 type
@@ -138,31 +126,29 @@
         that is, from high to low indices.
         -}
         Serial.Value n a,
-        Value Word),
-       Value Word)
+        LLVM.Value Word),
+       LLVM.Value Word)
 
 readSerialStart ::
-   (LLVM.IsPrimitive a, IsSized a, SizeOf a ~ asize,
-    TypeNum.Positive n, TypeNum.Positive (n :*: asize)) =>
+   (TypeNum.Positive n, Marshal.Vector n a) =>
    RingBuffer.T (Serial.Value n a) ->
-   CodeGenFunction r (Serial.Value n a, Iterator n a)
+   LLVM.CodeGenFunction r (Serial.Value n a, Iterator n a)
 readSerialStart rb = do
    a <- RingBuffer.index A.zero rb
    return (a, ((a, Tuple.undef, A.zero), A.zero))
 
 readSerialNext ::
-   (LLVM.IsPrimitive a, IsSized a, SizeOf a ~ asize,
-    TypeNum.Positive n, TypeNum.Positive (n :*: asize)) =>
+   (MultiValue.C a, Marshal.Vector n a) =>
    RingBuffer.T (Serial.Value n a) ->
    Iterator n a ->
-   CodeGenFunction r (Serial.Value n a, Iterator n a)
+   LLVM.CodeGenFunction r (Serial.Value n a, Iterator n a)
 readSerialNext rb ((a0,r0,j0), k0) = do
    vectorEnd <- A.cmp LLVM.CmpEQ j0 A.zero
    ((r1,j1), k1) <-
       C.ifThen vectorEnd ((r0,j0), k0) $ do
          k <- A.inc k0
          r <- RingBuffer.index k rb
-         return ((r, valueOf (fromIntegral $ Serial.size r :: Word)), k)
+         return ((r, LLVM.valueOf (Serial.size r :: Word)), k)
    j2 <- A.dec j1
    (ai,r2) <- Serial.shiftUp Tuple.undef r1
    (_, a1) <- Serial.shiftUp ai a0
diff --git a/src/Synthesizer/LLVM/Filter/SecondOrder.hs b/src/Synthesizer/LLVM/Filter/SecondOrder.hs
--- a/src/Synthesizer/LLVM/Filter/SecondOrder.hs
+++ b/src/Synthesizer/LLVM/Filter/SecondOrder.hs
@@ -1,15 +1,18 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Synthesizer.LLVM.Filter.SecondOrder (
    Parameter(Parameter),
    Filt2.c0, Filt2.c1, Filt2.c2, Filt2.d1, Filt2.d2,
    bandpassParameter,
+   bandpassParameterCode,
    ParameterStruct, composeParameter, decomposeParameter, -- for cascade
+   composeParameterMV, decomposeParameterMV,
+   causalExp,
    causal, causalPacked,
-   causalP, causalPackedP,
    ) where
 
 import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2
@@ -17,11 +20,15 @@
 
 import qualified Synthesizer.Plain.Modifier as Modifier
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Causal.Process as CausalExp
+import qualified Synthesizer.LLVM.Causal.ProcessValue as Causal
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as Serial
+import qualified Synthesizer.LLVM.Value as Value
 
+import qualified LLVM.DSL.Expression as Expr
+
+import qualified LLVM.Extra.Multi.Value.Marshal as MarshalMV
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Storable as Storable
 import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
@@ -38,8 +45,14 @@
 import qualified Control.Applicative.HT as App
 import Control.Arrow (arr, (<<<), (&&&))
 import Control.Monad (liftM2, foldM)
-import Control.Applicative (pure, (<$>), (<*>))
+import Control.Applicative (pure, liftA2, (<$>), (<*>))
 
+import qualified Data.Foldable as Fold
+import Data.Traversable (traverse)
+
+import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Module as Module
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -51,14 +64,6 @@
 instance Tuple.Undefined a => Tuple.Undefined (Parameter a) where
    undef = Tuple.undefPointed
 
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (Parameter a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
-
-instance LLVM.IsTuple a => LLVM.IsTuple (Parameter a) where
-   tupleDesc = Class.tupleDescFoldable
--}
-
 instance (Tuple.Value a) => Tuple.Value (Parameter a) where
    type ValueOf (Parameter a) = Parameter (Tuple.ValueOf a)
    valueOf = Tuple.valueOfFunctor
@@ -88,6 +93,18 @@
       <*> LLVM.extractvalue param TypeNum.d3
       <*> LLVM.extractvalue param TypeNum.d4
 
+decomposeParameterMV ::
+   (MarshalMV.C a) =>
+   LLVM.Value (MarshalMV.Struct (Parameter a)) ->
+   CodeGenFunction r (Filt2.Parameter (MultiValue.T a))
+decomposeParameterMV param =
+   pure Filt2.Parameter
+      <*> (Memory.decompose =<< LLVM.extractvalue param TypeNum.d0)
+      <*> (Memory.decompose =<< LLVM.extractvalue param TypeNum.d1)
+      <*> (Memory.decompose =<< LLVM.extractvalue param TypeNum.d2)
+      <*> (Memory.decompose =<< LLVM.extractvalue param TypeNum.d3)
+      <*> (Memory.decompose =<< LLVM.extractvalue param TypeNum.d4)
+
 composeParameter ::
    (LLVM.IsSized a) =>
    Filt2.Parameter (LLVM.Value a) ->
@@ -100,6 +117,20 @@
    (\param -> LLVM.insertvalue param d2_ TypeNum.d4) =<<
    return (LLVM.value LLVM.undef)
 
+composeParameterMV ::
+   (MarshalMV.C a) =>
+   Filt2.Parameter (MultiValue.T a) ->
+   CodeGenFunction r (LLVM.Value (MarshalMV.Struct (Parameter a)))
+composeParameterMV (Filt2.Parameter c0_ c1_ c2_ d1_ d2_) =
+   let insert field ix param =
+         Memory.compose field >>= flip (LLVM.insertvalue param) ix in
+   insert c0_ TypeNum.d0 =<<
+   insert c1_ TypeNum.d1 =<<
+   insert c2_ TypeNum.d2 =<<
+   insert d1_ TypeNum.d3 =<<
+   insert d2_ TypeNum.d4 =<<
+   return (LLVM.value LLVM.undef)
+
 instance (Memory.C a) => Memory.C (Parameter a) where
    type Struct (Parameter a) = ParameterStruct (Memory.Struct a)
    load = Memory.loadRecord parameterMemory
@@ -124,8 +155,47 @@
    flattenCode = Value.flattenCodeTraversable
    unfoldCode = Value.unfoldCodeTraversable
 
+instance (MultiValue.C a) => MultiValue.C (Parameter a) where
+   type Repr (Parameter a) = Parameter (MultiValue.Repr a)
+   cons = parameterMultiValue . fmap MultiValue.cons
+   undef = parameterMultiValue $ pure MultiValue.undef
+   zero = parameterMultiValue $ pure MultiValue.zero
+   phi bb =
+      fmap parameterMultiValue .
+      traverse (MultiValue.phi bb) .
+      parameterUnMultiValue
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb)
+         (parameterUnMultiValue a) (parameterUnMultiValue b)
 
+instance (MarshalMV.C a) => MarshalMV.C (Parameter a) where
+   pack p =
+      case MarshalMV.pack <$> p of
+         Filt2.Parameter c0_ c1_ c2_ d1_ d2_ ->
+            LLVM.consStruct c0_ c1_ c2_ d1_ d2_
+   unpack = fmap MarshalMV.unpack . LLVM.uncurryStruct Filt2.Parameter
 
+parameterMultiValue ::
+   Parameter (MultiValue.T a) -> MultiValue.T (Parameter a)
+parameterMultiValue =
+   MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
+
+parameterUnMultiValue ::
+   MultiValue.T (Parameter a) -> Parameter (MultiValue.T a)
+parameterUnMultiValue (MultiValue.Cons x) =
+   fmap MultiValue.Cons x
+
+instance
+   (Expr.Aggregate e mv) =>
+      Expr.Aggregate (Parameter e) (Parameter mv) where
+   type MultiValuesOf (Parameter e) = Parameter (Expr.MultiValuesOf e)
+   type ExpressionsOf (Parameter mv) = Parameter (Expr.ExpressionsOf mv)
+   bundle = traverse Expr.bundle
+   dissect = fmap Expr.dissect
+
+
+
 instance (Tuple.Phi a) => Tuple.Phi (Filt2.State a) where
    phi = Tuple.phiTraversable
    addPhi = Tuple.addPhiFoldable
@@ -159,25 +229,37 @@
    flattenCode = Value.flattenCodeTraversable
    unfoldCode = Value.unfoldCodeTraversable
 
+instance
+   (Expr.Aggregate e mv) =>
+      Expr.Aggregate (Filt2.State e) (Filt2.State mv) where
+   type MultiValuesOf (Filt2.State e) = Filt2.State (Expr.MultiValuesOf e)
+   type ExpressionsOf (Filt2.State mv) = Filt2.State (Expr.ExpressionsOf mv)
+   bundle = traverse Expr.bundle
+   dissect = fmap Expr.dissect
 
+
 {-# DEPRECATED bandpassParameter "only for testing, use Universal or Moog filter for production code" #-}
-bandpassParameter ::
+bandpassParameterCode ::
    (A.Transcendental a, A.RationalConstant a) =>
    a -> a ->
    CodeGenFunction r (Parameter a)
-bandpassParameter reson cutoff = do
+bandpassParameterCode reson cutoff = do
    rreson <- A.fdiv A.one reson
    k <- A.sub A.one rreson
    k2 <- A.neg =<< A.mul k k
    kcos <-
       A.mul (A.fromInteger' 2) =<< A.mul k =<<
       A.cos =<< A.mul cutoff =<<
-      Value.decons Value.twoPi
-   return $
-      Filt2.Parameter
-         rreson A.zero A.zero
-         kcos k2
+      Value.decons Value.tau
+   return $ Filt2.Parameter  rreson A.zero A.zero  kcos k2
 
+-- ToDo: move to synthesizer-core:Filter.SecondOrder (it is not the universal filter)
+bandpassParameter :: (Trans.C a) => a -> a -> Parameter a
+bandpassParameter reson cutoff =
+   let rreson = recip reson
+       k = one - rreson
+   in Filt2.Parameter  rreson zero zero  (2*k*cos(2*pi*cutoff)) (-k*k)
+
 modifier ::
    (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
    Modifier.Simple
@@ -188,49 +270,38 @@
    Filt2.modifier
 
 causal ::
-   (Causal.C process,
-    a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a, Memory.C v) =>
-   process (Parameter a, v) v
+   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a, Memory.C v) =>
+   Causal.T (Parameter a, v) v
 causal =
    Causal.fromModifier modifier
 
-{-# DEPRECATED causalP "use causal instead" #-}
-causalP ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a, Memory.C v) =>
-   CausalP.T p (Parameter a, v) v
-causalP =
-   CausalP.fromModifier modifier
+causalExp ::
+   (Expr.Aggregate ae a, Memory.C a, Module.C ae ve,
+    Expr.Aggregate ve v, Memory.C v) =>
+   CausalExp.T (Parameter a, v) v
+causalExp =
+   CausalExp.fromModifier Filt2.modifier
 
 
-{-# DEPRECATED causalPackedP "use causalPacked instead" #-}
-causalPackedP ::
-   (Serial.C v, Serial.Element v ~ a,
-    Memory.C v, Memory.C a, A.IntegerConstant v, A.IntegerConstant a,
-    A.PseudoRing v, A.PseudoRing a) =>
-   CausalP.T p (Parameter a, v) v
-causalPackedP = causalPacked
-
 {- |
 Vector size must be at least D2.
 -}
 causalPacked,
   causalRecursivePacked ::
-   (Causal.C process,
-    Serial.C v, Serial.Element v ~ a,
+   (Serial.Write v, Serial.Element v ~ a,
     Memory.C v, Memory.C a, A.IntegerConstant v, A.IntegerConstant a,
     A.PseudoRing v, A.PseudoRing a) =>
-   process (Parameter a, v) v
+   Causal.T (Parameter a, v) v
 causalPacked =
    causalRecursivePacked <<<
    (arr fst &&& causalNonRecursivePacked)
 
 _causalRecursivePackedAlt,
   causalNonRecursivePacked ::
-   (Causal.C process,
-    Serial.C v, Serial.Element v ~ a,
+   (Serial.Write v, Serial.Element v ~ a,
     Memory.C a, A.IntegerConstant v, A.IntegerConstant a,
     A.PseudoRing v, A.PseudoRing a) =>
-   process (Parameter a, v) v
+   Causal.T (Parameter a, v) v
 causalNonRecursivePacked =
    Causal.mapAccum
       (\(p, v0) (x1,x2) -> do
@@ -283,7 +354,7 @@
          d2v  <- Serial.upsample (Filt2.d2 p)
          d2vn <- A.neg d2v
 
-         y1  <- Serial.extract (valueOf $ fromIntegral size - 1) y1v
+         y1  <- Serial.last y1v
          xk1 <-
             Serial.modify (valueOf 0)
                (\u0 -> A.add u0 =<< A.mul (Filt2.d1 p) y1) =<<
diff --git a/src/Synthesizer/LLVM/Filter/SecondOrderCascade.hs b/src/Synthesizer/LLVM/Filter/SecondOrderCascade.hs
--- a/src/Synthesizer/LLVM/Filter/SecondOrderCascade.hs
+++ b/src/Synthesizer/LLVM/Filter/SecondOrderCascade.hs
@@ -1,35 +1,33 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE UndecidableInstances #-}
 module Synthesizer.LLVM.Filter.SecondOrderCascade (
-   causal,  causalPacked,
-   causalP, causalPackedP,
+   causal, causalPacked,
+   Parameter,
    ParameterValue(..),
    ParameterStruct,
    fixSize, constArray,
    ) where
 
 import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2
-import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2Core
 
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as Func
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as Sig
-import Synthesizer.LLVM.CausalParameterized.Functional (($&), (&|&))
+import qualified Synthesizer.LLVM.Causal.Functional as Func
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Private as Sig
 
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as Serial
 import Synthesizer.Causal.Class (($<))
 
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Extra.Memory as Memory
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core (Value, IsArithmetic, IsSized, CodeGenFunction)
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal.Number ((:*:))
@@ -37,19 +35,16 @@
 
 import Data.Word (Word)
 
-import qualified Control.Arrow as Arrow
-import Control.Arrow ((>>>), (<<<), (^<<), (&&&), arr)
-import Control.Applicative (liftA2)
-
+import Control.Arrow ((<<<), (^<<), (&&&), arr)
 
-import NumericPrelude.Numeric
 import NumericPrelude.Base
 
 
-type ParameterStruct n a = LLVM.Array n (Filt2.ParameterStruct a)
+type Parameter n a = MultiValue.Array n (Filt2.Parameter a)
+type ParameterStruct n a = Marshal.Struct (Parameter n a)
 
 newtype ParameterValue n a =
-   ParameterValue {parameterValue :: Value (ParameterStruct n a)}
+   ParameterValue {parameterValue :: MultiValue.T (Parameter n a)}
 {-
 Automatic deriving is not allowed even with GeneralizedNewtypeDeriving
 because of IsSized constraint
@@ -59,24 +54,20 @@
           Functor, App.Applicative, Fold.Foldable, Trav.Traversable)
 -}
 
-instance (TypeNum.Natural n, IsSized a) =>
+instance (TypeNum.Natural n, Marshal.C a) =>
       Tuple.Phi (ParameterValue n a) where
-   phi bb (ParameterValue r) =
-      fmap ParameterValue $ Tuple.phi bb r
-   addPhi bb
-        (ParameterValue r)
-        (ParameterValue r') =
-      Tuple.addPhi bb r r'
+   phi bb (ParameterValue r) = fmap ParameterValue $ MultiValue.phi bb r
+   addPhi bb (ParameterValue r) (ParameterValue r') = MultiValue.addPhi bb r r'
 
-instance (TypeNum.Natural n, IsSized a) =>
+instance (TypeNum.Natural n, Marshal.C a) =>
       Tuple.Undefined (ParameterValue n a) where
-   undef = ParameterValue Tuple.undef
+   undef = ParameterValue MultiValue.undef
 
-instance (TypeNum.Natural n, IsSized a) =>
+instance (TypeNum.Natural n, Marshal.C a) =>
       Tuple.Zero (ParameterValue n a) where
-   zero = ParameterValue Tuple.zero
+   zero = ParameterValue MultiValue.zero
 
-instance (TypeNum.Natural n, IsSized a,
+instance (TypeNum.Natural n, Marshal.C a,
           TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
       Memory.C (ParameterValue n a) where
    type Struct (ParameterValue n a) = ParameterStruct n a
@@ -103,54 +94,31 @@
 fixSize _n = id
 
 constArray ::
-   (TypeNum.Natural n, IsSized a) =>
-   Proxy n -> [LLVM.ConstValue a] ->
-   LLVM.Value (LLVM.Array n a)
-constArray _n = LLVM.value . LLVM.constArray
-
-
-causalP ::
-   (Memory.C v, A.PseudoModule v, A.Scalar v ~ LLVM.Value a,
-    IsSized a, IsArithmetic a, SoV.IntegerConstant a, TypeNum.Natural n,
-    TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   CausalP.T p (ParameterValue n a, v) v
-causalP = causal
-
-causalPackedP ::
-   (Memory.C v, A.PseudoRing v, A.IntegerConstant v, A.PseudoModule v,
-    Serial.C v, Serial.Element v ~ LLVM.Value a,
-    A.Scalar v ~ LLVM.Value a,
-    SoV.IntegerConstant a, LLVM.IsPrimitive a, IsSized a,
-    TypeNum.Positive (n :*: LLVM.UnknownSize),
-    TypeNum.Natural n) =>
-   CausalP.T p (ParameterValue n a, v) v
-causalPackedP = causalPacked
+   (TypeNum.Natural n, Marshal.C a) =>
+   Proxy n -> [a] -> MultiValue.T (MultiValue.Array n a)
+constArray _n = MultiValue.cons . MultiValue.Array
 
 
 causal ::
-   (Causal.C process,
-    Memory.C v, A.PseudoModule v, A.Scalar v ~ LLVM.Value a,
-    IsSized a, IsArithmetic a, SoV.IntegerConstant a, TypeNum.Natural n,
-    TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   process (ParameterValue n a, v) v
+   (A.PseudoModule v, Memory.C v, A.Scalar v ~ MultiValue.T a,
+    Marshal.C a, MultiValue.IntegerConstant a,
+    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
+   Causal.T (ParameterValue n a, v) v
 causal = causalGen Filt2.causal
 
 causalPacked ::
-   (Causal.C process,
-    A.PseudoRing v, A.IntegerConstant v,
-    Memory.C v, A.PseudoModule v, A.Scalar v ~ LLVM.Value a,
-    Serial.C v, Serial.Element v ~ LLVM.Value a,
-    SoV.IntegerConstant a, LLVM.IsPrimitive a, IsSized a,
-    TypeNum.Positive (n :*: LLVM.UnknownSize),
-    TypeNum.Natural n) =>
-   process (ParameterValue n a, v) v
+   (Marshal.C a, MultiValue.PseudoRing a, MultiValue.IntegerConstant a,
+    Serial.Write v, Serial.Element v ~ MultiValue.T a,
+    Memory.C v, A.PseudoRing v, A.IntegerConstant v,
+    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
+   Causal.T (ParameterValue n a, v) v
 causalPacked = causalGen Filt2.causalPacked
 
 causalGen ::
-   (Causal.C process, IsSized a, Tuple.Phi v, Tuple.Undefined v,
+   (Marshal.C a, Tuple.Phi v, Tuple.Undefined v,
     TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   process (Filt2Core.Parameter (Value a), v) v ->
-   process (ParameterValue n a, v) v
+   Causal.T (Filt2.Parameter (MultiValue.T a), v) v ->
+   Causal.T (ParameterValue n a, v) v
 causalGen stage =
    withSize $ \n ->
       snd
@@ -161,17 +129,17 @@
       <<<
       Causal.map
          (\(ptr, (p,v)) -> do
-            LLVM.store (parameterValue p) ptr
+            Memory.store (parameterValue p) ptr
             return (ptr, (A.zero, v)))
       $<
       Sig.alloca
 
 paramStage ::
-   (Causal.C process, IsSized a,
-    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   process (Filt2Core.Parameter (Value a), v) v ->
-   process
-      (Value (LLVM.Ptr (ParameterStruct n a)), (Value Word, v)) (Value Word, v)
+   (TypeNum.Natural n, Marshal.C a) =>
+   Causal.T (Filt2.Parameter (MultiValue.T a), v) v ->
+   Causal.T
+      (LLVM.Value (LLVM.Ptr (ParameterStruct n a)), (LLVM.Value Word, v))
+      (LLVM.Value Word, v)
 paramStage stage =
    let p = arr fst
        i = arr (fst.snd)
@@ -183,59 +151,12 @@
            &&&
            v)
 
-_paramStage ::
-   (IsSized a,
-    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   CausalP.T p (Filt2Core.Parameter (Value a), v) v ->
-   CausalP.T p
-      (Value (LLVM.Ptr (ParameterStruct n a)), (Value Word, v)) (Value Word, v)
-_paramStage stage =
-   Func.withGuidedArgs (Func.atom, (Func.atom, Func.atom)) $ \(p,(i,v)) ->
-      liftA2 (,) (i+1)
-         (stage $&
-             (Causal.zipWith getStageParameterGEP $& p &|& i)
-             &|&
-             v)
-
-_causalGenP ::
-   (Causal.C process, IsSized a,
-    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   process (Filt2Core.Parameter (Value a), v) v ->
-   process (ParameterValue n a, v) v
-_causalGenP stage =
-   withSize $ \n ->
-   foldl (\x y -> (arr fst &&& x) >>> y) (arr snd) $
-   map
-      (\k ->
-         stage <<<
-         Arrow.first (Causal.map (flip getStageParameter k)))
-      (take (TypeNum.integralFromSingleton n) [0..])
-
-
-getStageParameter ::
-   (IsSized a,
-    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   ParameterValue n a ->
-   Word ->
-   CodeGenFunction r (Filt2Core.Parameter (Value a))
-getStageParameter ps k =
-   Filt2.decomposeParameter =<< LLVM.extractvalue (parameterValue ps) k
-{-
-   Memory.decompose =<<
-   flip LLVM.extractvalue k =<<
-   Memory.compose ps
--}
-
 getStageParameterGEP ::
-   (IsSized a,
-    TypeNum.Natural n, TypeNum.Positive (n :*: LLVM.UnknownSize)) =>
-   Value (LLVM.Ptr (ParameterStruct n a)) ->
-   Value Word -> CodeGenFunction r (Filt2Core.Parameter (Value a))
+   (TypeNum.Natural n,  Marshal.C a) =>
+   LLVM.Value (LLVM.Ptr (ParameterStruct n a)) ->
+   LLVM.Value Word ->
+   LLVM.CodeGenFunction r (Filt2.Parameter (MultiValue.T a))
 getStageParameterGEP ptr k =
-   Filt2.decomposeParameter
+   Filt2.decomposeParameterMV
     =<< LLVM.load
     =<< LLVM.getElementPtr0 ptr (k, ())
-
-
-{-# DEPRECATED causalP          "use 'causal' instead" #-}
-{-# DEPRECATED causalPackedP    "use 'causalPacked' instead" #-}
diff --git a/src/Synthesizer/LLVM/Filter/SecondOrderPacked.hs b/src/Synthesizer/LLVM/Filter/SecondOrderPacked.hs
--- a/src/Synthesizer/LLVM/Filter/SecondOrderPacked.hs
+++ b/src/Synthesizer/LLVM/Filter/SecondOrderPacked.hs
@@ -1,37 +1,34 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE UndecidableInstances #-}
 module Synthesizer.LLVM.Filter.SecondOrderPacked (
-   Parameter, bandpassParameter, State, causal, causalP,
+   Parameter, ParameterExp, bandpassParameter, State, causal,
    ) where
 
 import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2L
 import qualified Synthesizer.Plain.Filter.Recursive.SecondOrder as Filt2
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp(Exp))
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
 
 import qualified LLVM.Core as LLVM
-import LLVM.Core
-   (Value, valueOf, Struct,
-    IsFirstClass, IsFloating,
-    Vector, IsPrimitive, IsSized,
-    CodeGenFunction)
 
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal (D4, d0, d1, (:*:))
+import Type.Data.Num.Decimal (D4, d0, d1)
 
 import Control.Applicative (liftA2)
 
-import qualified Algebra.Transcendental as Trans
-
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -41,10 +38,9 @@
 
 > c0 [c1 d1 c2 d2]
 -}
-data Parameter a =
-   Parameter (Value a) (Value (Vector D4 a))
+data Parameter a = Parameter (MultiValue.T a) (MultiVector.T D4 a)
 
-instance (IsFirstClass a, IsPrimitive a) => Tuple.Phi (Parameter a) where
+instance (MultiVector.C a) => Tuple.Phi (Parameter a) where
    phi bb (Parameter r i) = do
       r' <- Tuple.phi bb r
       i' <- Tuple.phi bb i
@@ -53,23 +49,21 @@
       Tuple.addPhi bb r r'
       Tuple.addPhi bb i i'
 
-instance (IsFirstClass a, IsPrimitive a) => Tuple.Undefined (Parameter a) where
+instance (MultiVector.C a) => Tuple.Undefined (Parameter a) where
    undef = Parameter Tuple.undef Tuple.undef
 
 
-type ParameterStruct a = Struct (a, (Vector D4 a, ()))
+type ParameterStruct a = Memory.Struct (MultiValue.T a, MultiVector.T D4 a)
 
 parameterMemory ::
-   (IsPrimitive a, IsSized a, TypeNum.Positive (D4 :*: LLVM.SizeOf a)) =>
+   (Marshal.C a, Marshal.Vector D4 a) =>
    Memory.Record r (ParameterStruct a) (Parameter a)
 parameterMemory =
    liftA2 Parameter
       (Memory.element (\(Parameter c0 _) -> c0) d0)
       (Memory.element (\(Parameter _ cd) -> cd) d1)
 
-instance
-   (IsPrimitive a, IsSized a, TypeNum.Positive (D4 :*: LLVM.SizeOf a)) =>
-      Memory.C (Parameter a) where
+instance (Marshal.C a, Marshal.Vector D4 a) => Memory.C (Parameter a) where
    type Struct (Parameter a) = ParameterStruct a
    load = Memory.loadRecord parameterMemory
    store = Memory.storeRecord parameterMemory
@@ -77,44 +71,60 @@
    compose = Memory.composeRecord parameterMemory
 
 
-type State = Vector D4
+data ParameterExp a =
+   ParameterExp (forall r. LLVM.CodeGenFunction r (Parameter a))
 
+instance Expr.Aggregate (ParameterExp a) (Parameter a) where
+   type MultiValuesOf (ParameterExp a) = Parameter a
+   type ExpressionsOf (Parameter a) = ParameterExp a
+   dissect x = ParameterExp (return x)
+   bundle (ParameterExp code) = code
 
+
+type State = MultiVector.T D4
+
+
 {-# DEPRECATED bandpassParameter "only for testing, use Universal or Moog filter for production code" #-}
 bandpassParameter ::
-   (Trans.C a, IsFloating a, SoV.TranscendentalConstant a, IsPrimitive a) =>
-   Value a ->
-   Value a ->
-   CodeGenFunction r (Parameter a)
-bandpassParameter reson cutoff = do
-   p <- Filt2L.bandpassParameter reson cutoff
-   v <- Vector.assemble [Filt2.c1 p, Filt2.d1 p, Filt2.c2 p, Filt2.d2 p]
+   (MultiVector.C a, MultiValue.Transcendental a,
+    MultiValue.RationalConstant a) =>
+   Exp a -> Exp a -> ParameterExp a
+bandpassParameter (Exp reson) (Exp cutoff) =
+   ParameterExp (do
+      r <- reson
+      c <- cutoff
+      bandpassParameterCode r c)
+
+bandpassParameterCode ::
+   (MultiVector.C a, MultiValue.Transcendental a,
+    MultiValue.RationalConstant a) =>
+   MultiValue.T a ->
+   MultiValue.T a ->
+   LLVM.CodeGenFunction r (Parameter a)
+bandpassParameterCode reson cutoff = do
+   p <- Filt2L.bandpassParameterCode reson cutoff
+   v <-
+      MultiVector.assembleFromVector $ fmap ($ p) $
+      LLVM.consVector Filt2.c1 Filt2.d1 Filt2.c2 Filt2.d2
    return $ Parameter (Filt2.c0 p) v
 
 
 next ::
-   (Vector.Arithmetic a) =>
-   (Parameter a, Value a) ->
-   Value (State a) ->
-   CodeGenFunction r (Value a, Value (State a))
+   (MultiVector.PseudoRing a) =>
+   (Parameter a, MultiValue.T a) ->
+   State a ->
+   LLVM.CodeGenFunction r (MultiValue.T a, State a)
 next (Parameter c0 k1, x0) y1 = do
    s0 <- A.mul c0 x0
-   s1 <- Vector.dotProduct k1 y1
+   s1 <- MultiVector.dotProduct k1 y1
    y0 <- A.add s0 s1
-   x1new <- Vector.extract (valueOf 0) y1
-   y1new <- Vector.extract (valueOf 1) y1
-   yv <- Vector.assemble [x0, y0, x1new, y1new]
+   x1new <- MultiVector.extract (LLVM.valueOf 0) y1
+   y1new <- MultiVector.extract (LLVM.valueOf 1) y1
+   yv <- MultiVector.assembleFromVector $ LLVM.consVector x0 y0 x1new y1new
    return (y0, yv)
 
 causal ::
-   (Causal.C process,
-    Vector.Arithmetic a, Value (State a) ~ value, Memory.C value) =>
-   process (Parameter a, Value a) (Value a)
-causal =
-   Causal.mapAccum next (return A.zero)
-
-{-# DEPRECATED causalP "use causal instead" #-}
-causalP ::
-   (Vector.Arithmetic a, Value (State a) ~ value, Memory.C value) =>
-   CausalP.T p (Parameter a, Value a) (Value a)
-causalP = causal
+   (MultiVector.PseudoRing a) =>
+   (Marshal.Vector D4 a) =>
+   Causal.T (Parameter a, MultiValue.T a) (MultiValue.T a)
+causal = Causal.mapAccum next (return A.zero)
diff --git a/src/Synthesizer/LLVM/Filter/Universal.hs b/src/Synthesizer/LLVM/Filter/Universal.hs
--- a/src/Synthesizer/LLVM/Filter/Universal.hs
+++ b/src/Synthesizer/LLVM/Filter/Universal.hs
@@ -1,22 +1,31 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Synthesizer.LLVM.Filter.Universal (
    Result(Result, lowpass, highpass, bandpass, bandlimit),
-   Parameter, parameter, causal, causalP,
+   Parameter, parameter, causal,
+   parameterCode, causalExp,
+   multiValueResult, unMultiValueResult,
+   multiValueParameter, unMultiValueParameter,
    ) where
 
 import qualified Synthesizer.Plain.Filter.Recursive.Universal as Universal
 import Synthesizer.Plain.Filter.Recursive.Universal
-          (Parameter(Parameter), Result)
+          (Parameter(Parameter), Result(..))
 import Synthesizer.Plain.Filter.Recursive (Pole(..))
 
 import qualified Synthesizer.Plain.Modifier as Modifier
 
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Causal.Process as CausalExp
+import qualified Synthesizer.LLVM.Causal.ProcessValue as Causal
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as Serial
+import qualified Synthesizer.LLVM.Value as Value
 
+import qualified LLVM.DSL.Expression as Expr
+
+import qualified LLVM.Extra.Multi.Value.Marshal as MarshalMV
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Storable as Storable
 import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
@@ -30,9 +39,15 @@
 import Type.Data.Num.Decimal (d0, d1, d2, d3, d4, d5)
 
 import qualified Control.Applicative.HT as App
-import Control.Applicative ((<$>))
+import Control.Applicative (liftA2, (<$>))
 
+import qualified Data.Foldable as Fold
+import Data.Traversable (traverse)
 
+import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Module as Module
+
+
 instance (Tuple.Phi a) => Tuple.Phi (Parameter a) where
    phi = Tuple.phiTraversable
    addPhi = Tuple.addPhiFoldable
@@ -74,14 +89,28 @@
    load = Storable.loadApplicative
    store = Storable.storeFoldable
 
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (Result a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
 
-instance LLVM.IsTuple a => LLVM.IsTuple (Result a) where
-   tupleDesc = Class.tupleDescFoldable
--}
 
+type ResultStruct a = LLVM.Struct (a, (a, (a, (a, ()))))
+
+resultMemory ::
+   (Memory.C a) =>
+   Memory.Record r (ResultStruct (Memory.Struct a)) (Result a)
+resultMemory =
+   App.lift4 Result
+      (Memory.element Universal.highpass  d0)
+      (Memory.element Universal.bandpass  d1)
+      (Memory.element Universal.lowpass   d2)
+      (Memory.element Universal.bandlimit d3)
+
+
+instance (Memory.C a) => Memory.C (Result a) where
+   type Struct (Result a) = ResultStruct (Memory.Struct a)
+   load = Memory.loadRecord resultMemory
+   store = Memory.storeRecord resultMemory
+   decompose = Memory.decomposeRecord resultMemory
+   compose = Memory.composeRecord resultMemory
+
 instance (Tuple.Value a) => Tuple.Value (Result a) where
    type ValueOf (Result a) = Result (Tuple.ValueOf a)
    valueOf = Tuple.valueOfFunctor
@@ -91,15 +120,40 @@
    flattenCode = Value.flattenCodeTraversable
    unfoldCode = Value.unfoldCodeTraversable
 
+instance (MultiValue.C a) => MultiValue.C (Result a) where
+   type Repr (Result a) = Result (MultiValue.Repr a)
+   cons = multiValueResult . fmap MultiValue.cons
+   undef = multiValueResult $ pure MultiValue.undef
+   zero = multiValueResult $ pure MultiValue.zero
+   phi bb =
+      fmap multiValueResult .
+      traverse (MultiValue.phi bb) . unMultiValueResult
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb)
+         (unMultiValueResult a) (unMultiValueResult b)
 
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (Parameter a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
+multiValueResult ::
+   Result (MultiValue.T a) -> MultiValue.T (Result a)
+multiValueResult = MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
 
-instance LLVM.IsTuple a => LLVM.IsTuple (Parameter a) where
-   tupleDesc = Class.tupleDescFoldable
--}
+unMultiValueResult ::
+   MultiValue.T (Result a) -> Result (MultiValue.T a)
+unMultiValueResult (MultiValue.Cons x) = fmap MultiValue.Cons x
 
+instance (MarshalMV.C a) => MarshalMV.C (Result a) where
+   pack p =
+      case MarshalMV.pack <$> p of
+         Result hp bp lp bl -> LLVM.consStruct hp bp lp bl
+   unpack = fmap MarshalMV.unpack . LLVM.uncurryStruct Result
+
+instance (Expr.Aggregate e mv) => Expr.Aggregate (Result e) (Result mv) where
+   type MultiValuesOf (Result e) = Result (Expr.MultiValuesOf e)
+   type ExpressionsOf (Result mv) = Result (Expr.ExpressionsOf mv)
+   bundle = traverse Expr.bundle
+   dissect = fmap Expr.dissect
+
+
 instance (Tuple.Value a) => Tuple.Value (Parameter a) where
    type ValueOf (Parameter a) = Parameter (Tuple.ValueOf a)
    valueOf = Tuple.valueOfFunctor
@@ -109,7 +163,43 @@
    flattenCode = Value.flattenCodeTraversable
    unfoldCode = Value.unfoldCodeTraversable
 
+instance (MultiValue.C a) => MultiValue.C (Parameter a) where
+   type Repr (Parameter a) = Parameter (MultiValue.Repr a)
+   cons = multiValueParameter . fmap MultiValue.cons
+   undef = multiValueParameter $ pure MultiValue.undef
+   zero = multiValueParameter $ pure MultiValue.zero
+   phi bb =
+      fmap multiValueParameter .
+      traverse (MultiValue.phi bb) . unMultiValueParameter
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb)
+         (unMultiValueParameter a) (unMultiValueParameter b)
 
+multiValueParameter ::
+   Parameter (MultiValue.T a) -> MultiValue.T (Parameter a)
+multiValueParameter = MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
+
+unMultiValueParameter ::
+   MultiValue.T (Parameter a) -> Parameter (MultiValue.T a)
+unMultiValueParameter (MultiValue.Cons x) = fmap MultiValue.Cons x
+
+instance (MarshalMV.C a) => MarshalMV.C (Parameter a) where
+   pack p =
+      case MarshalMV.pack <$> p of
+         Parameter k1 k2 ampIn ampI1 ampI2 ampLimit ->
+            LLVM.consStruct k1 k2 ampIn ampI1 ampI2 ampLimit
+   unpack = fmap MarshalMV.unpack . LLVM.uncurryStruct Parameter
+
+instance
+   (Expr.Aggregate e mv) =>
+      Expr.Aggregate (Parameter e) (Parameter mv) where
+   type MultiValuesOf (Parameter e) = Parameter (Expr.MultiValuesOf e)
+   type ExpressionsOf (Parameter mv) = Parameter (Expr.ExpressionsOf mv)
+   bundle = traverse Expr.bundle
+   dissect = fmap Expr.dissect
+
+
 instance (Vector.Simple v) => Vector.Simple (Parameter v) where
    type Element (Parameter v) = Parameter (Vector.Element v)
    type Size (Parameter v) = Vector.Size v
@@ -146,7 +236,7 @@
    readStart = Serial.readStartTraversable
    readNext = Serial.readNextTraversable
 
-instance (Serial.C v) => Serial.C (Result v) where
+instance (Serial.Write v) => Serial.Write (Result v) where
    type WriteIt (Result v) = Result (Serial.WriteIt v)
    insert  = Serial.insertTraversable
    writeStart = Serial.writeStartTraversable
@@ -154,14 +244,17 @@
    writeStop = Serial.writeStopTraversable
 
 
-parameter ::
+parameterCode ::
    (A.Transcendental a, A.RationalConstant a) =>
    a -> a -> CodeGenFunction r (Parameter a)
-parameter =
+parameterCode =
    Value.unlift2 $ \reson freq ->
    Universal.parameter (Pole reson freq)
 
+parameter :: (Trans.C a) => a -> a -> Parameter a
+parameter reson freq = Universal.parameter (Pole reson freq)
 
+
 modifier ::
    (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
    Modifier.Simple
@@ -172,16 +265,14 @@
    Universal.modifier
 
 causal ::
-   (Causal.C process,
-    a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a, Memory.C v) =>
-   process (Parameter a, v) (Result v)
+   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a, Memory.C v) =>
+   Causal.T (Parameter a, v) (Result v)
 causal = Causal.fromModifier modifier
 
-{-# DEPRECATED causalP "use causal instead" #-}
-causalP ::
-   (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a, Memory.C v) =>
-   CausalP.T p (Parameter a, v) (Result v)
-causalP = causal
+causalExp ::
+   (Module.C ae ve, Expr.Aggregate ae a, Expr.Aggregate ve v, Memory.C v) =>
+   CausalExp.T (Parameter a, v) (Result v)
+causalExp = CausalExp.fromModifier Universal.modifier
 
 {-
 The state variable filter could be vectorised
diff --git a/src/Synthesizer/LLVM/ForeignPtr.hs b/src/Synthesizer/LLVM/ForeignPtr.hs
--- a/src/Synthesizer/LLVM/ForeignPtr.hs
+++ b/src/Synthesizer/LLVM/ForeignPtr.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {- |
 Adding the finalizer to a ForeignPtr seems to be the only way
 that warrants execution of the finalizer (not too early and not never).
@@ -12,6 +13,7 @@
 module Synthesizer.LLVM.ForeignPtr where
 
 import qualified LLVM.DSL.Execution as Exec
+import qualified LLVM.Extra.Multi.Value.Marshal as MarshalMV
 import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.ExecutionEngine as EE
 import qualified LLVM.Core as LLVM
@@ -47,6 +49,14 @@
    b -> IO (MemoryPtr a)
 newParam stop start b =
    newInit stop (Marshal.with b start)
+
+newParamMV ::
+   (MarshalMV.C b) =>
+   Exec.Finalizer a ->
+   (LLVM.Ptr (MarshalMV.Struct b) -> IO (LLVM.Ptr a)) ->
+   b -> IO (MemoryPtr a)
+newParamMV stop start b =
+   newInit stop (MarshalMV.with b start)
 
 new ::
    (Marshal.C a, Marshal.Struct a ~ struct) =>
diff --git a/src/Synthesizer/LLVM/Frame/Binary.hs b/src/Synthesizer/LLVM/Frame/Binary.hs
--- a/src/Synthesizer/LLVM/Frame/Binary.hs
+++ b/src/Synthesizer/LLVM/Frame/Binary.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module Synthesizer.LLVM.Frame.Binary (
    toCanonical,
    ) where
diff --git a/src/Synthesizer/LLVM/Frame/SerialVector.hs b/src/Synthesizer/LLVM/Frame/SerialVector.hs
--- a/src/Synthesizer/LLVM/Frame/SerialVector.hs
+++ b/src/Synthesizer/LLVM/Frame/SerialVector.hs
@@ -1,8 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeOperators #-}
 {- |
 A special vector type that represents a time-sequence of samples.
 This way we can distinguish safely between LLVM vectors
@@ -14,648 +11,99 @@
 -}
 module Synthesizer.LLVM.Frame.SerialVector (
    T(Cons),
-   Plain, Value,
-   plain, value, constant,
-
-   Read, Element, ReadIt, extract, readStart, readNext,
-   C, WriteIt, insert, writeStart, writeNext, writeStop,
-   Zero, writeZero,
-   Iterator(Iterator), ReadIterator, WriteIterator, ReadMode, WriteMode,
-
-   Sized, Size, size, sizeOfIterator, withSize,
-
-   insertTraversable, extractTraversable,
-   readStartTraversable, readNextTraversable,
-   writeStartTraversable, writeNextTraversable, writeStopTraversable,
-   writeZeroTraversable,
-
-   extractAll, assemble, modify,
+   fromFixedList,
    upsample, subsample,
-   cumulate, iterate, iteratePlain, reverse,
-   shiftUp, shiftUpMultiZero, shiftDownMultiZero,
-   replicate, replicate_, replicateOf, fromList, fromFixedList,
-   mapPlain, mapV, zipV,
+   shiftUp,
+   reverse, iterate, cumulate,
+   limit,
+   select, cmp,
    ) where
 
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Code
+import Synthesizer.LLVM.Frame.SerialVector.Code
+         (T, fromMultiVector, toMultiVector)
 
-import qualified LLVM.Extra.Vector as Vector
+import qualified LLVM.DSL.Expression.Vector as ExprVec
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value.Vector as MultiValueVec
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
 
 import qualified LLVM.Core as LLVM
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
-import qualified Foreign.Storable as St
 import Data.Word (Word32)
 
-import Control.Monad (liftM2, liftM3, foldM, replicateM, (<=<))
-import Control.Applicative (liftA2)
-import qualified Control.Monad.Trans.State as MS
-import qualified Control.Applicative as App
-import qualified Data.Traversable as Trav
-
-import qualified Data.NonEmpty.Class as NonEmptyC
-import qualified Data.NonEmpty as NonEmpty
-import qualified Data.List.HT as ListHT
-import qualified Data.List as List
-import Data.Tuple.HT (mapSnd, fst3, snd3, thd3)
-
-import Prelude hiding (Read, replicate, reverse, iterate)
-
-
-{-
-This datatype can be used for both Haskell vector and LLVM.Value Vector.
-It should not contain tuples of vectors,
-since the interpretation is:
-"Everything inside Cons will be virtually concatenated."
-
-We tried to use distinct types (T n a) and (Value n a)
-for Haskell and LLVM objects, respectively,
-but then GHC-6.12.3 to GHC-7.4.1 could not perform the GeneralizedNewtypeDeriving,
-because it was not able to add a (IsPositive n ~ True) constraint
-to the instances.
-
-The disadvantage of this approach is,
-that we cannot have a type that contains both parallel and serial data.
--}
-newtype T v = Cons v
-   deriving (
-      Eq, St.Storable,
-      Tuple.Zero, Tuple.Undefined,
-      A.IntegerConstant, A.RationalConstant, Num)
---      SoV.IntegerConstant, SoV.RationalConstant, SoV.TranscendentalConstant)
-
-instance (Tuple.Phi v) => Tuple.Phi (T v) where
-   phi bb (Cons v) = fmap Cons $ Tuple.phi bb v
-   addPhi bb (Cons x) (Cons y) = Tuple.addPhi bb x y
-
-instance (A.Additive v) => A.Additive (T v) where
-   add = lift2 A.add
-   sub = lift2 A.sub
-   neg = lift1 A.neg
-   zero = Cons A.zero
-
-instance (A.PseudoRing v) => A.PseudoRing (T v) where
-   mul = lift2 A.mul
-
-instance (A.Real v) => A.Real (T v) where
-   min = lift2 A.min
-   max = lift2 A.max
-   abs = lift1 A.abs
-   signum = lift1 A.signum
-
-instance (A.Fraction v) => A.Fraction (T v) where
-   truncate = lift1 A.truncate
-   fraction = lift1 A.fraction
-
-instance (A.Field v) => A.Field (T v) where
-   fdiv = lift2 A.fdiv
-
-instance (A.Algebraic v) => A.Algebraic (T v) where
-   sqrt = lift1 A.sqrt
-
-instance (A.Transcendental v) => A.Transcendental (T v) where
-   pi  = fmap Cons A.pi
-   sin = lift1 A.sin
-   log = lift1 A.log
-   exp = lift1 A.exp
-   cos = lift1 A.cos
-   pow = lift2 A.pow
-
-
-lift1 :: Functor f => (a -> f b) -> T a -> f (T b)
-lift1 f (Cons x) = fmap Cons $ f x
-
-lift2 :: Functor f => (a -> b -> f c) -> T a -> T b -> f (T c)
-lift2 f (Cons x) (Cons y) = fmap Cons $ f x y
-
-
-type instance A.Scalar (T v) = A.Scalar v
-instance (A.PseudoModule v) => A.PseudoModule (T v) where
-   scale a (Cons v) = fmap Cons $ A.scale a v
-
-
-type Plain n a = T (LLVM.Vector n a)
-type Value n a = T (LLVM.Value (LLVM.Vector n a))
-
-
-plain :: LLVM.Vector n a -> Plain n a
-plain = Cons
-
-value :: LLVM.Value (LLVM.Vector n a) -> Value n a
-value = Cons
+import Prelude hiding (replicate, reverse, iterate)
 
 
-replicate :: (TypeNum.Positive n) => a -> Plain n a
-replicate x = Cons $ App.pure x
-
-replicate_ :: (TypeNum.Positive n) => TypeNum.Singleton n -> a -> Plain n a
-replicate_ _ = replicate
-
-replicateOf :: (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsConst a) => a -> Value n a
-replicateOf x = Cons $ LLVM.valueOf $ App.pure x
-
-fromList :: (TypeNum.Positive n) => NonEmpty.T [] a -> Plain n a
-fromList = Cons . LLVM.cyclicVector
-
 fromFixedList ::
-   (TypeNum.Positive n) =>
-   LLVM.FixedList (TypeNum.ToUnary n) a -> Plain n a
-fromFixedList = Cons . LLVM.vector
+   (TypeNum.Positive n, MultiVector.C a) =>
+   LLVM.FixedList (TypeNum.ToUnary n) a -> Exp (T n a)
+fromFixedList = fromOrdinary . Expr.cons . LLVM.vector
 
-constant :: (TypeNum.Positive n) => a -> T (Vector.Constant n a)
-constant = Cons . Vector.constant
 
 
-newtype Iterator mode it v = Iterator {unIterator :: it}
-   deriving (Tuple.Undefined)
-
-instance Tuple.Phi it => Tuple.Phi (Iterator mode it v) where
-   phi bb (Iterator x) = fmap Iterator $ Tuple.phi bb x
-   addPhi bb (Iterator x) (Iterator y) = Tuple.addPhi bb x y
-
-
-type ReadIterator = Iterator ReadMode
-type WriteIterator = Iterator WriteMode
-
-data ReadMode
-data WriteMode
-
-
-instance (Memory.C it) => Memory.C (Iterator mode it v) where
-   type Struct (Iterator mode it v) = Memory.Struct it
-   load = Memory.loadNewtype Iterator
-   store = Memory.storeNewtype (\(Iterator v) -> v)
-   decompose = Memory.decomposeNewtype Iterator
-   compose = Memory.composeNewtype (\(Iterator v) -> v)
-
-
-fmapIt ::
-   (ita -> itb) -> (va -> vb) ->
-   Iterator mode ita va -> Iterator mode itb vb
-fmapIt f _ (Iterator a) = Iterator (f a)
-
-
-combineIt2 :: Iterator mode xa va -> Iterator mode xb vb -> Iterator mode (xa,xb) (va,vb)
-combineIt2 (Iterator va) (Iterator vb) = Iterator (va,vb)
-
-combineIt3 :: Iterator mode xa va -> Iterator mode xb vb -> Iterator mode xc vc -> Iterator mode (xa,xb,xc) (va,vb,vc)
-combineIt3 (Iterator va) (Iterator vb) (Iterator vc) = Iterator (va,vb,vc)
-
-combineItFunctor ::
-   (Functor f) =>
-   f (Iterator mode x v) -> Iterator mode (f x) (f v)
-combineItFunctor =
-   Iterator . fmap unIterator
-
-sequenceItFunctor ::
-   (Functor f) =>
-   Iterator mode (f it) (f v) ->
-   f (Iterator mode it v)
-sequenceItFunctor =
-   fmap Iterator . unIterator
-
-
-class
-   (TypeNum.Positive (Size v), Sized v,
-    Tuple.Phi (ReadIt v), Tuple.Undefined (ReadIt v),
-    Tuple.Phi v, Tuple.Undefined v) =>
-      Read v where
-
-   type Element v :: *
-   type ReadIt v :: *
-
-   extract :: LLVM.Value Word32 -> v -> LLVM.CodeGenFunction r (Element v)
-
-   extractAll :: v -> LLVM.CodeGenFunction r [Element v]
-   extractAll x =
-      mapM
-         (flip extract x . LLVM.valueOf)
-         (take (size x) [0..])
-
-   readStart :: v -> LLVM.CodeGenFunction r (ReadIterator (ReadIt v) v)
-   readNext ::
-      ReadIterator (ReadIt v) v ->
-      LLVM.CodeGenFunction r (Element v, ReadIterator (ReadIt v) v)
-
-class (Read v, Tuple.Phi (WriteIt v), Tuple.Undefined (WriteIt v)) => C v where
-   type WriteIt v :: *
-
-   insert :: LLVM.Value Word32 -> Element v -> v -> LLVM.CodeGenFunction r v
-
-   assemble :: [Element v] -> LLVM.CodeGenFunction r v
-   assemble =
-      foldM (\v (k,x) -> insert (LLVM.valueOf k) x v) Tuple.undef .
-      zip [0..]
-
-   writeStart :: LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)
-   writeNext ::
-      Element v -> WriteIterator (WriteIt v) v ->
-      LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)
-   writeStop :: WriteIterator (WriteIt v) v -> LLVM.CodeGenFunction r v
-
-class (C v, Tuple.Phi (WriteIt v), Tuple.Zero (WriteIt v)) => Zero v where
-   -- initializes the target with zeros
-   -- you may only call 'writeStop' on the result of 'writeZero'
-   writeZero :: LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)
-
-instance (Vector.Simple v) => Sized (T v) where
-   type Size (T v) = Vector.Size v
-
-{- |
-This instance also allows to wrap tuples of vectors,
-but you cannot reasonably use them,
-because it would mean to serialize vectors with different element types.
--}
-instance (Vector.Simple v) => Read (T v) where
-
-   type Element (T v) = Vector.Element v
-   type ReadIt (T v) = v
-
-   extract k (Cons v) = Vector.extract k v
-
-   readStart (Cons v) = return $ Iterator v
-   readNext (Iterator v0) = do
-      x <- Vector.extract (LLVM.valueOf 0) v0
-      v1 <- Vector.rotateDown v0
-      return (x, Iterator v1)
-
-
-instance (Vector.C v) => C (T v) where
-   type WriteIt (T v) = v
-
-   insert k a (Cons v) = fmap Cons $ Vector.insert k a v
-
-   writeStart = return (Iterator Tuple.undef)
-   writeNext x (Iterator v0) = do
-      v1 <- fmap snd $ Vector.shiftDown x v0
-      return (Iterator v1)
-   writeStop (Iterator v0) = return (Cons v0)
-
-instance (Vector.C v, Tuple.Zero v) => Zero (T v) where
-   writeZero = return (Iterator Tuple.zero)
-
-
-instance
-   (Read va, Read vb, Size va ~ Size vb) =>
-      Read (va, vb) where
-
-   type Element (va, vb) = (Element va, Element vb)
-   type ReadIt (va, vb) = (ReadIt va, ReadIt vb)
-
-   extract k (va,vb) =
-      liftM2 (,)
-         (extract k va)
-         (extract k vb)
-
-   readStart (va,vb) =
-      liftM2 combineIt2 (readStart va) (readStart vb)
-   readNext it = do
-      (a, ita) <- readNext $ fmapIt fst fst it
-      (b, itb) <- readNext $ fmapIt snd snd it
-      return ((a,b), combineIt2 ita itb)
-
-instance
-   (C va, C vb, Size va ~ Size vb) =>
-      C (va, vb) where
-
-   type WriteIt (va, vb) = (WriteIt va, WriteIt vb)
-
-   insert k (a,b) (va,vb) =
-      liftM2 (,)
-         (insert k a va)
-         (insert k b vb)
-
-   writeStart =
-      liftM2 combineIt2 writeStart writeStart
-   writeNext (a,b) it =
-      liftM2 combineIt2
-         (writeNext a $ fmapIt fst fst it)
-         (writeNext b $ fmapIt snd snd it)
-   writeStop it =
-      liftM2 (,)
-         (writeStop (fmapIt fst fst it))
-         (writeStop (fmapIt snd snd it))
-
-instance
-   (Zero va, Zero vb, Size va ~ Size vb) =>
-      Zero (va, vb) where
-
-   writeZero =
-      liftM2 combineIt2 writeZero writeZero
-
-
-instance
-   (Read va, Read vb, Read vc,
-    Size va ~ Size vb,
-    Size vb ~ Size vc) =>
-      Read (va, vb, vc) where
-
-   type Element (va, vb, vc) = (Element va, Element vb, Element vc)
-   type ReadIt (va, vb, vc) = (ReadIt va, ReadIt vb, ReadIt vc)
-
-   extract k (va,vb,vc) =
-      liftM3 (,,)
-         (extract k va)
-         (extract k vb)
-         (extract k vc)
-
-   readStart (va,vb,vc) =
-      liftM3 combineIt3 (readStart va) (readStart vb) (readStart vc)
-   readNext it = do
-      (a, ita) <- readNext $ fmapIt fst3 fst3 it
-      (b, itb) <- readNext $ fmapIt snd3 snd3 it
-      (c, itc) <- readNext $ fmapIt thd3 thd3 it
-      return ((a,b,c), combineIt3 ita itb itc)
-
-
-instance
-   (C va, C vb, C vc,
-    Size va ~ Size vb,
-    Size vb ~ Size vc) =>
-      C (va, vb, vc) where
-
-   type WriteIt (va, vb, vc) = (WriteIt va, WriteIt vb, WriteIt vc)
-
-   insert k (a,b,c) (va,vb,vc) =
-      liftM3 (,,)
-         (insert k a va)
-         (insert k b vb)
-         (insert k c vc)
-
-   writeStart =
-      liftM3 combineIt3 writeStart writeStart writeStart
-   writeNext (a,b,c) it =
-      liftM3 combineIt3
-         (writeNext a $ fmapIt fst3 fst3 it)
-         (writeNext b $ fmapIt snd3 snd3 it)
-         (writeNext c $ fmapIt thd3 thd3 it)
-   writeStop it =
-      liftM3 (,,)
-         (writeStop (fmapIt fst3 fst3 it))
-         (writeStop (fmapIt snd3 snd3 it))
-         (writeStop (fmapIt thd3 thd3 it))
-
-instance
-   (Zero va, Zero vb, Zero vc,
-    Size va ~ Size vb,
-    Size vb ~ Size vc) =>
-      Zero (va, vb, vc) where
-
-   writeZero =
-      liftM3 combineIt3 writeZero writeZero writeZero
-
-
-instance (Read v) => Read (Stereo.T v) where
-
-   type Element (Stereo.T v) = Stereo.T (Element v)
-   type ReadIt (Stereo.T v) = Stereo.T (ReadIt v)
-
-   extract = extractTraversable
-
-   readStart = readStartTraversable
-   readNext = readNextTraversable
-
-instance (C v) => C (Stereo.T v) where
-
-   type WriteIt (Stereo.T v) = Stereo.T (WriteIt v)
-
-   insert = insertTraversable
-
-   writeStart = writeStartTraversable
-   writeNext = writeNextTraversable
-   writeStop = writeStopTraversable
-
-instance (Zero v) => Zero (Stereo.T v) where
-
-   writeZero = writeZeroTraversable
-
-
-modify ::
-   (C v) =>
-   LLVM.Value Word32 ->
-   (Element v -> LLVM.CodeGenFunction r (Element v)) ->
-   v -> LLVM.CodeGenFunction r v
-modify k f v = do
-   flip (insert k) v =<< f =<< extract k v
-
-
-subsample ::
-   (Read v) =>
-   v -> LLVM.CodeGenFunction r (Element v)
-subsample v =
-   extract (A.zero :: LLVM.Value Word32) v
+subsample :: (TypeNum.Positive n, MultiVector.C a) => Exp (T n a) -> Exp a
+subsample =
+   Expr.liftM (MultiValueVec.extract (A.zero :: LLVM.Value Word32)) . toOrdinary
 
--- this will be translated to an efficient pshufd
-upsample ::
-   (C v) =>
-   Element v -> LLVM.CodeGenFunction r v
-upsample x =
-   withSize $ \n -> assemble $ List.replicate n x
+upsample :: (TypeNum.Positive n, MultiVector.C a) => Exp a -> Exp (T n a)
+upsample = fromOrdinary . ExprVec.replicate
 
 
-cumulate ::
-   (Vector.Arithmetic a, TypeNum.Positive n) =>
-   LLVM.Value a -> Value n a ->
-   LLVM.CodeGenFunction r (LLVM.Value a, Value n a)
-cumulate x (Cons v) =
-   fmap (mapSnd Cons) $ Vector.cumulate x v
+shiftUp ::
+   (TypeNum.Positive n, MultiVector.C x, Exp x ~ a, Exp (T n x) ~ v) =>
+   a -> v -> (a, v)
+shiftUp a v =
+   (Expr.liftM2 ((fmap fst .) . Code.shiftUp) a v,
+    Expr.liftM2 ((fmap snd .) . Code.shiftUp) a v)
 
 
-mapPlain ::
-   (TypeNum.Positive n) => (a -> b) -> Plain n a -> Plain n b
-mapPlain f (Cons v) = Cons $ fmap f v
-
-iteratePlain ::
-   (TypeNum.Positive n) => (a -> a) -> a -> Plain n a
-iteratePlain f x = fromList $ NonEmptyC.iterate f x
-
 iterate ::
-   (C v) =>
-   (Element v -> LLVM.CodeGenFunction r (Element v)) ->
-   Element v -> LLVM.CodeGenFunction r v
-iterate f x =
-   withSize $ \n ->
-      assemble =<<
-      (flip MS.evalStateT x $
-       replicateM n $
-       MS.StateT $ \x0 -> do x1 <- f x0; return (x0,x1))
+   (TypeNum.Positive n, MultiVector.C a) =>
+   (Exp a -> Exp a) -> Exp a -> Exp (T n a)
+iterate f = fromOrdinary . ExprVec.iterate f
 
 reverse ::
-   (C v) =>
-   v -> LLVM.CodeGenFunction r v
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Exp (T n a) -> Exp (T n a)
 reverse =
-   assemble . List.reverse <=< extractAll
-
-shiftUp ::
-   (C v) =>
-   Element v -> v -> LLVM.CodeGenFunction r (Element v, v)
-shiftUp x v =
-   ListHT.switchR
-      (return (x,v))
-      (\ys0 y -> fmap ((,) y) $ assemble (x:ys0))
-   =<<
-   extractAll v
-
-
-shiftUpMultiZero ::
-   (C v, A.Additive (Element v)) =>
-   Int -> v -> LLVM.CodeGenFunction r v
-shiftUpMultiZero n v =
-   assemble . take (size v) . (List.replicate n A.zero ++) =<< extractAll v
-
-shiftDownMultiZero ::
-   (C v, A.Additive (Element v)) =>
-   Int -> v -> LLVM.CodeGenFunction r v
-shiftDownMultiZero n v =
-   assemble . take (size v) . (++ List.repeat A.zero) . List.drop n
-      =<< extractAll v
-
-
-insertTraversable ::
-   (C v, Trav.Traversable f, App.Applicative f) =>
-   LLVM.Value Word32 -> f (Element v) -> f v -> LLVM.CodeGenFunction r (f v)
-insertTraversable n a v =
-   Trav.sequence (liftA2 (insert n) a v)
-
-extractTraversable ::
-   (Read v, Trav.Traversable f) =>
-   LLVM.Value Word32 -> f v -> LLVM.CodeGenFunction r (f (Element v))
-extractTraversable n v =
-   Trav.mapM (extract n) v
-
-
-readStartTraversable ::
-   (Trav.Traversable f, App.Applicative f, Read v) =>
-   f v -> LLVM.CodeGenFunction r (ReadIterator (f (ReadIt v)) (f v))
-readNextTraversable ::
-   (Trav.Traversable f, App.Applicative f, Read v) =>
-   ReadIterator (f (ReadIt v)) (f v) ->
-   LLVM.CodeGenFunction r (f (Element v), ReadIterator (f (ReadIt v)) (f v))
-
-readStartTraversable v =
-   fmap combineItFunctor $ Trav.mapM readStart v
-
-readNextTraversable it = do
-   st <- Trav.mapM readNext $ sequenceItFunctor it
-   return (fmap fst st, combineItFunctor $ fmap snd st)
-
-
-writeStartTraversable ::
-   (Trav.Traversable f, App.Applicative f, C v) =>
-   LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))
-writeNextTraversable ::
-   (Trav.Traversable f, App.Applicative f, C v) =>
-   f (Element v) -> WriteIterator (f (WriteIt v)) (f v) ->
-   LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))
-writeStopTraversable ::
-   (Trav.Traversable f, App.Applicative f, C v) =>
-   WriteIterator (f (WriteIt v)) (f v) -> LLVM.CodeGenFunction r (f v)
-writeZeroTraversable ::
-   (Trav.Traversable f, App.Applicative f, Zero v) =>
-   LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))
-
-writeStartTraversable =
-   fmap combineItFunctor $ Trav.sequence $ App.pure writeStart
-
-writeNextTraversable x it =
-   fmap combineItFunctor $ Trav.sequence $
-   liftA2 writeNext x $ sequenceItFunctor it
-
-writeStopTraversable = Trav.mapM writeStop . sequenceItFunctor
-
-writeZeroTraversable =
-   fmap combineItFunctor $ Trav.sequence $ App.pure writeZero
-
-
-instance (Tuple.Value v) => Tuple.Value (T v) where
-   type ValueOf (T v) = T (Tuple.ValueOf v)
-   valueOf (Cons v) = Cons (Tuple.valueOf v)
-
-instance (Memory.C v) => Memory.C (T v) where
-   type Struct (T v) = Memory.Struct v
-   load = Memory.loadNewtype Cons
-   store = Memory.storeNewtype (\(Cons v) -> v)
-   decompose = Memory.decomposeNewtype Cons
-   compose = Memory.composeNewtype (\(Cons v) -> v)
-
-instance (Marshal.C v) => Marshal.C (T v) where
-   pack (Cons v) = Marshal.pack v
-   unpack v = Cons $ Marshal.unpack v
-
-instance (Storable.C v) => Storable.C (T v) where
-   load = Storable.loadNewtype Cons Cons
-   store = Storable.storeNewtype Cons (\(Cons v) -> v)
+   Expr.liftM (fmap fromMultiVector . MultiVector.reverse . toMultiVector)
 
 
-mapV :: (Functor m) =>
-   (LLVM.Value (LLVM.Vector n a) -> m (LLVM.Value (LLVM.Vector n b))) ->
-   Value n a -> m (Value n b)
-mapV f (Cons x) = fmap Cons (f x)
-
-zipV :: (Functor m) =>
-   (c -> d) ->
-   (LLVM.Value (LLVM.Vector n a) ->
-    LLVM.Value (LLVM.Vector n b) ->
-    m c) ->
-   Value n a ->
-   Value n b ->
-   m d
-zipV g f (Cons x) (Cons y) =
-   fmap g (f x y)
+cumulate ::
+   (TypeNum.Positive n, MultiVector.Additive a) =>
+   Exp a -> Exp (T n a) -> (Exp a, Exp (T n a))
+cumulate a v =
+   (Expr.liftM2 ((fmap fst .) . Code.cumulate) a v,
+    Expr.liftM2 ((fmap snd .) . Code.cumulate) a v)
 
+limit ::
+   (TypeNum.Positive n, MultiVector.Real a) =>
+   (Exp (T n a), Exp (T n a)) -> Exp (T n a) -> Exp (T n a)
+limit (l,u) =
+   fromOrdinary . ExprVec.limit (toOrdinary l, toOrdinary u) . toOrdinary
 
 
-withSize :: Sized v => (Int -> m v) -> m v
-withSize =
-   let sz :: (Sized v) => TypeNum.Singleton (Size v) -> (Int -> m v) -> m v
-       sz n f = f (TypeNum.integralFromSingleton n)
-   in  sz TypeNum.singleton
-
-size :: Sized v => v -> Int
-size =
-   let sz :: (Sized v) => TypeNum.Singleton (Size v) -> v -> Int
-       sz n _ = TypeNum.integralFromSingleton n
-   in  sz TypeNum.singleton
+cmp ::
+   (TypeNum.Positive n, MultiVector.Comparison a) =>
+   LLVM.CmpPredicate -> Exp (T n a) -> Exp (T n a) -> Exp (T n Bool)
+cmp ord a b = fromOrdinary $ ExprVec.cmp ord (toOrdinary a) (toOrdinary b)
 
-sizeOfIterator :: Sized v => Iterator mode it v -> Int
-sizeOfIterator =
-   let sz :: Sized v => TypeNum.Singleton (Size v) -> Iterator mode it v -> Int
-       sz n _ = TypeNum.integralFromSingleton n
-   in  sz TypeNum.singleton
+select ::
+   (TypeNum.Positive n, MultiVector.Select a) =>
+   Exp (T n Bool) -> Exp (T n a) -> Exp (T n a) -> Exp (T n a)
+select c a b =
+   fromOrdinary $ ExprVec.select (toOrdinary c) (toOrdinary a) (toOrdinary b)
 
 
-{- |
-The type parameter @value@ shall be a virtual LLVM register
-or a wrapper around one or more virtual LLVM registers.
--}
-class (TypeNum.Positive (Size valueTuple)) => Sized valueTuple where
-   type Size valueTuple :: *
-
-{- |
-Basic LLVM types are all counted as scalar values, even LLVM Vectors.
-This means that an LLVM Vector can be used for parallel handling of data.
--}
-instance Sized (LLVM.Value a) where
-   type Size (LLVM.Value a) = TypeNum.D1
-
-instance (Sized value) => Sized (Stereo.T value) where
-   type Size (Stereo.T value) = Size value
-
-instance
-   (Sized value0, Sized value1,
-    Size value0 ~ Size value1) =>
-      Sized (value0, value1) where
-   type Size (value0, value1) = Size value0
+fromOrdinary :: Exp (LLVM.Vector n a) -> Exp (T n a)
+fromOrdinary = Expr.lift1 MultiValue.cast
 
-instance
-   (Sized value0, Sized value1, Sized value2,
-    Size value0 ~ Size value1,
-    Size value1 ~ Size value2) =>
-      Sized (value0, value1, value2) where
-   type Size (value0, value1, value2) = Size value0
+toOrdinary :: Exp (T n a) -> Exp (LLVM.Vector n a)
+toOrdinary = Expr.lift1 MultiValue.cast
diff --git a/src/Synthesizer/LLVM/Frame/SerialVector/Class.hs b/src/Synthesizer/LLVM/Frame/SerialVector/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Frame/SerialVector/Class.hs
@@ -0,0 +1,523 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{- |
+A special vector type that represents a time-sequence of samples.
+This way we can distinguish safely between LLVM vectors
+used for parallel signals and pipelines and
+those used for chunky processing of scalar signals.
+For the chunky processing this data type allows us
+to derive the factor from the type
+that time constants have to be multiplied with.
+-}
+module Synthesizer.LLVM.Frame.SerialVector.Class (
+   Constant(Constant), constant,
+
+   Read, Element, ReadIt, extract, readStart, readNext,
+   Write, WriteIt, insert, writeStart, writeNext, writeStop,
+   Zero, writeZero,
+   Iterator(Iterator), ReadIterator, WriteIterator, ReadMode, WriteMode,
+
+   Sized, Size, size, sizeOfIterator, withSize,
+
+   insertTraversable, extractTraversable,
+   readStartTraversable, readNextTraversable,
+   writeStartTraversable, writeNextTraversable, writeStopTraversable,
+   writeZeroTraversable,
+
+   dissect, assemble, modify,
+   upsample, subsample, last,
+   iterate, reverse,
+   shiftUp, shiftUpMultiZero, shiftDownMultiZero,
+   ) where
+
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as SerialCode
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import Data.Word (Word32)
+
+import qualified Control.Monad.Trans.State as MS
+import qualified Control.Applicative as App
+import Control.Monad (foldM, replicateM, (<=<))
+import Control.Applicative (liftA2, liftA3, (<$>))
+
+import qualified Data.Traversable as Trav
+import qualified Data.List.HT as ListHT
+import qualified Data.List as List
+import Data.Tuple.HT (mapSnd, fst3, snd3, thd3)
+
+import Prelude hiding (Read, replicate, reverse, iterate, last)
+
+
+
+newtype Constant n a = Constant a
+
+constant :: (TypeNum.Positive n) => a -> Constant n a
+constant = Constant
+
+instance Functor (Constant n) where
+   fmap f (Constant a) = Constant (f a)
+
+instance App.Applicative (Constant n) where
+   pure = Constant
+   Constant f <*> Constant a = Constant (f a)
+
+instance (Tuple.Phi a) => Tuple.Phi (Constant n a) where
+   phi bb (Constant a) = Constant <$> Tuple.phi bb a
+   addPhi bb (Constant a) (Constant b) = Tuple.addPhi bb a b
+
+instance (Tuple.Undefined a) => Tuple.Undefined (Constant n a) where
+   undef = Tuple.undefPointed
+
+
+
+instance (TypeNum.Positive n) => Sized (Constant n a) where
+   type Size (Constant n a) = n
+
+instance
+   (TypeNum.Positive n, Tuple.Phi a, Tuple.Undefined a) =>
+      Read (Constant n a) where
+
+   type Element (Constant n a) = a
+   type ReadIt (Constant n a) = a
+
+   extract _k (Constant a) = return a
+
+   readStart (Constant a) = return $ Iterator a
+   readNext it@(Iterator a) = return (a, it)
+
+
+
+newtype Iterator mode it v = Iterator {unIterator :: it}
+   deriving (Tuple.Undefined)
+
+instance Tuple.Phi it => Tuple.Phi (Iterator mode it v) where
+   phi bb (Iterator x) = fmap Iterator $ Tuple.phi bb x
+   addPhi bb (Iterator x) (Iterator y) = Tuple.addPhi bb x y
+
+
+type ReadIterator = Iterator ReadMode
+type WriteIterator = Iterator WriteMode
+
+data ReadMode
+data WriteMode
+
+
+instance (Memory.C it) => Memory.C (Iterator mode it v) where
+   type Struct (Iterator mode it v) = Memory.Struct it
+   load = Memory.loadNewtype Iterator
+   store = Memory.storeNewtype (\(Iterator v) -> v)
+   decompose = Memory.decomposeNewtype Iterator
+   compose = Memory.composeNewtype (\(Iterator v) -> v)
+
+
+fmapIt ::
+   (ita -> itb) -> (va -> vb) ->
+   Iterator mode ita va -> Iterator mode itb vb
+fmapIt f _ (Iterator a) = Iterator (f a)
+
+
+combineIt2 ::
+   Iterator mode xa va -> Iterator mode xb vb ->
+   Iterator mode (xa,xb) (va,vb)
+combineIt2 (Iterator va) (Iterator vb) = Iterator (va,vb)
+
+combineIt3 ::
+   Iterator mode xa va -> Iterator mode xb vb -> Iterator mode xc vc ->
+   Iterator mode (xa,xb,xc) (va,vb,vc)
+combineIt3 (Iterator va) (Iterator vb) (Iterator vc) = Iterator (va,vb,vc)
+
+combineItFunctor ::
+   (Functor f) => f (Iterator mode x v) -> Iterator mode (f x) (f v)
+combineItFunctor = Iterator . fmap unIterator
+
+sequenceItFunctor ::
+   (Functor f) => Iterator mode (f it) (f v) -> f (Iterator mode it v)
+sequenceItFunctor = fmap Iterator . unIterator
+
+
+withSize :: Sized v => (Int -> m v) -> m v
+withSize =
+   let sz :: (Sized v) => TypeNum.Singleton (Size v) -> (Int -> m v) -> m v
+       sz n f = f (TypeNum.integralFromSingleton n)
+   in  sz TypeNum.singleton
+
+size :: (Sized v, Integral i) => v -> i
+size =
+   let sz :: (Sized v, Integral i) => TypeNum.Singleton (Size v) -> v -> i
+       sz n _ = TypeNum.integralFromSingleton n
+   in  sz TypeNum.singleton
+
+sizeOfIterator :: (Sized v, Integral i) => Iterator mode it v -> i
+sizeOfIterator =
+   let sz :: (Sized v, Integral i) =>
+               TypeNum.Singleton (Size v) -> Iterator mode it v -> i
+       sz n _ = TypeNum.integralFromSingleton n
+   in  sz TypeNum.singleton
+
+
+{- |
+The type parameter @v@ shall be a @MultiVector@ or @MultiValue Serial@
+or a wrapper around one or more such things sharing the same size.
+-}
+class (TypeNum.Positive (Size v)) => Sized v where
+   type Size v
+
+class
+   (Sized v,
+    Tuple.Phi (ReadIt v), Tuple.Undefined (ReadIt v),
+    Tuple.Phi v, Tuple.Undefined v) =>
+      Read v where
+
+   type Element v
+   type ReadIt v
+
+   extract :: LLVM.Value Word32 -> v -> LLVM.CodeGenFunction r (Element v)
+
+   dissect :: v -> LLVM.CodeGenFunction r [Element v]
+   dissect x = mapM (flip extract x . LLVM.valueOf) (take (size x) [0..])
+
+   readStart :: v -> LLVM.CodeGenFunction r (ReadIterator (ReadIt v) v)
+   readNext ::
+      ReadIterator (ReadIt v) v ->
+      LLVM.CodeGenFunction r (Element v, ReadIterator (ReadIt v) v)
+
+class
+   (Read v, Tuple.Phi (WriteIt v), Tuple.Undefined (WriteIt v)) =>
+      Write v where
+   type WriteIt v
+
+   insert :: LLVM.Value Word32 -> Element v -> v -> LLVM.CodeGenFunction r v
+
+   assemble :: [Element v] -> LLVM.CodeGenFunction r v
+   assemble =
+      foldM (\v (k,x) -> insert (LLVM.valueOf k) x v) Tuple.undef . zip [0..]
+
+   writeStart :: LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)
+   writeNext ::
+      Element v -> WriteIterator (WriteIt v) v ->
+      LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)
+   writeStop :: WriteIterator (WriteIt v) v -> LLVM.CodeGenFunction r v
+
+class (Write v, Tuple.Phi (WriteIt v), Tuple.Zero (WriteIt v)) => Zero v where
+   -- initializes the target with zeros
+   -- you may only call 'writeStop' on the result of 'writeZero'
+   writeZero :: LLVM.CodeGenFunction r (WriteIterator (WriteIt v) v)
+
+
+
+instance (TypeNum.Positive n) => Sized (MultiVector.T n a) where
+   type Size (MultiVector.T n a) = n
+
+instance (TypeNum.Positive n, MultiVector.C a) => Read (MultiVector.T n a) where
+
+   type Element (MultiVector.T n a) = MultiValue.T a
+   type ReadIt (MultiVector.T n a) = MultiVector.T n a
+
+   extract = MultiVector.extract
+
+   readStart v = return $ Iterator v
+   readNext (Iterator v) =
+      mapSnd Iterator <$> MultiVector.shiftDown MultiValue.undef v
+
+instance
+      (TypeNum.Positive n, MultiVector.C a) => Write (MultiVector.T n a) where
+
+   type WriteIt (MultiVector.T n a) = MultiVector.T n a
+
+   insert = MultiVector.insert
+
+   writeStart = return (Iterator MultiVector.undef)
+   writeNext x (Iterator v) = Iterator . snd <$> MultiVector.shiftDown x v
+   writeStop (Iterator v) = return v
+
+instance (TypeNum.Positive n, MultiVector.C a) => Zero (MultiVector.T n a) where
+   writeZero = return (Iterator Tuple.zero)
+
+
+
+type Serial n a = SerialCode.Value n a
+
+instance (TypeNum.Positive n) => Sized (Serial n a) where
+   type Size (Serial n a) = n
+
+instance (TypeNum.Positive n, MultiVector.C a) => Read (Serial n a) where
+
+   type Element (Serial n a) = MultiValue.T a
+   type ReadIt (Serial n a) = Serial n a
+
+   extract = SerialCode.extract
+
+   readStart v = return $ Iterator v
+   readNext (Iterator v) =
+      mapSnd Iterator <$> SerialCode.shiftDown MultiValue.undef v
+
+instance (TypeNum.Positive n, MultiVector.C a) => Write (Serial n a) where
+
+   type WriteIt (Serial n a) = Serial n a
+
+   insert = SerialCode.insert
+
+   writeStart = return (Iterator Tuple.undef)
+   writeNext x (Iterator v) = Iterator . snd <$> SerialCode.shiftDown x v
+   writeStop (Iterator v) = return v
+
+instance (TypeNum.Positive n, MultiVector.C a) => Zero (Serial n a) where
+   writeZero = return (Iterator Tuple.zero)
+
+
+
+instance (Sized va, Sized vb, Size va ~ Size vb) => Sized (va, vb) where
+   type Size (va, vb) = Size va
+
+instance (Read va, Read vb, Size va ~ Size vb) => Read (va, vb) where
+
+   type Element (va, vb) = (Element va, Element vb)
+   type ReadIt (va, vb) = (ReadIt va, ReadIt vb)
+
+   extract k (va,vb) = liftA2 (,) (extract k va) (extract k vb)
+
+   readStart (va,vb) = liftA2 combineIt2 (readStart va) (readStart vb)
+   readNext it = do
+      (a, ita) <- readNext $ fmapIt fst fst it
+      (b, itb) <- readNext $ fmapIt snd snd it
+      return ((a,b), combineIt2 ita itb)
+
+instance (Write va, Write vb, Size va ~ Size vb) => Write (va, vb) where
+
+   type WriteIt (va, vb) = (WriteIt va, WriteIt vb)
+
+   insert k (a,b) (va,vb) =
+      liftA2 (,)
+         (insert k a va)
+         (insert k b vb)
+
+   writeStart = liftA2 combineIt2 writeStart writeStart
+   writeNext (a,b) it =
+      liftA2 combineIt2
+         (writeNext a $ fmapIt fst fst it)
+         (writeNext b $ fmapIt snd snd it)
+   writeStop it =
+      liftA2 (,)
+         (writeStop (fmapIt fst fst it))
+         (writeStop (fmapIt snd snd it))
+
+instance (Zero va, Zero vb, Size va ~ Size vb) => Zero (va, vb) where
+   writeZero = liftA2 combineIt2 writeZero writeZero
+
+
+instance
+   (Sized va, Sized vb, Sized vc, Size va ~ Size vb, Size vb ~ Size vc) =>
+      Sized (va, vb, vc) where
+   type Size (va, vb, vc) = Size va
+
+instance
+   (Read va, Read vb, Read vc, Size va ~ Size vb, Size vb ~ Size vc) =>
+      Read (va, vb, vc) where
+
+   type Element (va, vb, vc) = (Element va, Element vb, Element vc)
+   type ReadIt (va, vb, vc) = (ReadIt va, ReadIt vb, ReadIt vc)
+
+   extract k (va,vb,vc) =
+      liftA3 (,,)
+         (extract k va)
+         (extract k vb)
+         (extract k vc)
+
+   readStart (va,vb,vc) =
+      liftA3 combineIt3 (readStart va) (readStart vb) (readStart vc)
+   readNext it = do
+      (a, ita) <- readNext $ fmapIt fst3 fst3 it
+      (b, itb) <- readNext $ fmapIt snd3 snd3 it
+      (c, itc) <- readNext $ fmapIt thd3 thd3 it
+      return ((a,b,c), combineIt3 ita itb itc)
+
+
+instance
+   (Write va, Write vb, Write vc, Size va ~ Size vb, Size vb ~ Size vc) =>
+      Write (va, vb, vc) where
+
+   type WriteIt (va, vb, vc) = (WriteIt va, WriteIt vb, WriteIt vc)
+
+   insert k (a,b,c) (va,vb,vc) =
+      liftA3 (,,)
+         (insert k a va)
+         (insert k b vb)
+         (insert k c vc)
+
+   writeStart = liftA3 combineIt3 writeStart writeStart writeStart
+   writeNext (a,b,c) it =
+      liftA3 combineIt3
+         (writeNext a $ fmapIt fst3 fst3 it)
+         (writeNext b $ fmapIt snd3 snd3 it)
+         (writeNext c $ fmapIt thd3 thd3 it)
+   writeStop it =
+      liftA3 (,,)
+         (writeStop (fmapIt fst3 fst3 it))
+         (writeStop (fmapIt snd3 snd3 it))
+         (writeStop (fmapIt thd3 thd3 it))
+
+instance
+   (Zero va, Zero vb, Zero vc, Size va ~ Size vb, Size vb ~ Size vc) =>
+      Zero (va, vb, vc) where
+
+   writeZero = liftA3 combineIt3 writeZero writeZero writeZero
+
+
+instance (Sized value) => Sized (Stereo.T value) where
+   type Size (Stereo.T value) = Size value
+
+instance (Read v) => Read (Stereo.T v) where
+
+   type Element (Stereo.T v) = Stereo.T (Element v)
+   type ReadIt (Stereo.T v) = Stereo.T (ReadIt v)
+
+   extract = extractTraversable
+
+   readStart = readStartTraversable
+   readNext = readNextTraversable
+
+instance (Write v) => Write (Stereo.T v) where
+
+   type WriteIt (Stereo.T v) = Stereo.T (WriteIt v)
+
+   insert = insertTraversable
+
+   writeStart = writeStartTraversable
+   writeNext = writeNextTraversable
+   writeStop = writeStopTraversable
+
+instance (Zero v) => Zero (Stereo.T v) where
+
+   writeZero = writeZeroTraversable
+
+
+insertTraversable ::
+   (Write v, Trav.Traversable f, App.Applicative f) =>
+   LLVM.Value Word32 -> f (Element v) -> f v -> LLVM.CodeGenFunction r (f v)
+insertTraversable n a v =
+   Trav.sequence (liftA2 (insert n) a v)
+
+extractTraversable ::
+   (Read v, Trav.Traversable f) =>
+   LLVM.Value Word32 -> f v -> LLVM.CodeGenFunction r (f (Element v))
+extractTraversable n v =
+   Trav.mapM (extract n) v
+
+
+readStartTraversable ::
+   (Trav.Traversable f, App.Applicative f, Read v) =>
+   f v -> LLVM.CodeGenFunction r (ReadIterator (f (ReadIt v)) (f v))
+readNextTraversable ::
+   (Trav.Traversable f, App.Applicative f, Read v) =>
+   ReadIterator (f (ReadIt v)) (f v) ->
+   LLVM.CodeGenFunction r (f (Element v), ReadIterator (f (ReadIt v)) (f v))
+
+readStartTraversable v =
+   fmap combineItFunctor $ Trav.mapM readStart v
+
+readNextTraversable it = do
+   st <- Trav.mapM readNext $ sequenceItFunctor it
+   return (fmap fst st, combineItFunctor $ fmap snd st)
+
+
+writeStartTraversable ::
+   (Trav.Traversable f, App.Applicative f, Write v) =>
+   LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))
+writeNextTraversable ::
+   (Trav.Traversable f, App.Applicative f, Write v) =>
+   f (Element v) -> WriteIterator (f (WriteIt v)) (f v) ->
+   LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))
+writeStopTraversable ::
+   (Trav.Traversable f, App.Applicative f, Write v) =>
+   WriteIterator (f (WriteIt v)) (f v) -> LLVM.CodeGenFunction r (f v)
+writeZeroTraversable ::
+   (Trav.Traversable f, App.Applicative f, Zero v) =>
+   LLVM.CodeGenFunction r (WriteIterator (f (WriteIt v)) (f v))
+
+writeStartTraversable =
+   fmap combineItFunctor $ Trav.sequence $ App.pure writeStart
+
+writeNextTraversable x it =
+   fmap combineItFunctor $ Trav.sequence $
+   liftA2 writeNext x $ sequenceItFunctor it
+
+writeStopTraversable = Trav.mapM writeStop . sequenceItFunctor
+
+writeZeroTraversable =
+   fmap combineItFunctor $ Trav.sequence $ App.pure writeZero
+
+
+modify ::
+   (Write v, Element v ~ a) =>
+   LLVM.Value Word32 ->
+   (a -> LLVM.CodeGenFunction r a) ->
+   v -> LLVM.CodeGenFunction r v
+modify k f v = flip (insert k) v =<< f =<< extract k v
+
+
+last :: (Read v) => v -> LLVM.CodeGenFunction r (Element v)
+last v = extract (LLVM.valueOf (size v - 1 :: Word32)) v
+
+subsample :: (Read v) => v -> LLVM.CodeGenFunction r (Element v)
+subsample v = extract (A.zero :: LLVM.Value Word32) v
+
+-- this will be translated to an efficient pshufd
+upsample :: (Write v) => Element v -> LLVM.CodeGenFunction r v
+upsample x = withSize $ \n -> assemble $ List.replicate n x
+
+
+iterate ::
+   (Write v) =>
+   (Element v -> LLVM.CodeGenFunction r (Element v)) ->
+   Element v -> LLVM.CodeGenFunction r v
+iterate f x =
+   withSize $ \n ->
+      assemble =<<
+      (flip MS.evalStateT x $
+       replicateM n $
+       MS.StateT $ \x0 -> do x1 <- f x0; return (x0,x1))
+
+reverse ::
+   (Write v) =>
+   v -> LLVM.CodeGenFunction r v
+reverse =
+   assemble . List.reverse <=< dissect
+
+shiftUp ::
+   (Write v) =>
+   Element v -> v -> LLVM.CodeGenFunction r (Element v, v)
+shiftUp x v =
+   ListHT.switchR
+      (return (x,v))
+      (\ys0 y -> fmap ((,) y) $ assemble (x:ys0))
+   =<<
+   dissect v
+
+
+shiftUpMultiZero ::
+   (Write v, A.Additive (Element v)) =>
+   Int -> v -> LLVM.CodeGenFunction r v
+shiftUpMultiZero n v =
+   assemble . take (size v) . (List.replicate n A.zero ++) =<< dissect v
+
+shiftDownMultiZero ::
+   (Write v, A.Additive (Element v)) =>
+   Int -> v -> LLVM.CodeGenFunction r v
+shiftDownMultiZero n v =
+   assemble . take (size v) . (++ List.repeat A.zero) . List.drop n
+      =<< dissect v
diff --git a/src/Synthesizer/LLVM/Frame/SerialVector/Code.hs b/src/Synthesizer/LLVM/Frame/SerialVector/Code.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Frame/SerialVector/Code.hs
@@ -0,0 +1,279 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module Synthesizer.LLVM.Frame.SerialVector.Code (
+   T(Cons), Value, size,
+   fromOrdinary, toOrdinary,
+   fromMultiVector, toMultiVector,
+   extract, insert, modify,
+   assemble, dissect,
+   assemble1, dissect1,
+   upsample, subsample, last,
+   reverse, shiftUp, shiftUpMultiZero, shiftDown,
+   cumulate, iterate,
+   scale,
+   ) where
+
+import qualified LLVM.Extra.Multi.Vector.Instance as MultiVectorInst
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Vector as MultiValueVec
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Arithmetic as A
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Foreign.Storable as Store
+import Foreign.Storable (Storable)
+import Foreign.Ptr (castPtr)
+
+import Control.Applicative ((<$>))
+
+import qualified Data.NonEmpty as NonEmpty
+import Data.Word (Word32)
+import Data.Tuple.HT (mapSnd)
+
+import Prelude as P hiding (last, reverse, iterate)
+
+
+newtype T n a = Cons (LLVM.Vector n a)
+   deriving (Eq, Num)
+
+type Value n a = MultiValue.T (T n a)
+
+instance (TypeNum.Positive n, MultiVector.C a) => MultiValue.C (T n a) where
+   type Repr (T n a) = MultiVector.Repr n a
+   cons (Cons v) = fromOrdinary $ MultiValue.cons v
+   undef = fromOrdinary MultiValue.undef
+   zero = fromOrdinary MultiValue.zero
+   phi bb = fmap fromOrdinary . MultiValue.phi bb . toOrdinary
+   addPhi bb a b = MultiValue.addPhi bb (toOrdinary a) (toOrdinary b)
+
+instance (Marshal.Vector n a) => Marshal.C (T n a) where
+   pack (Cons v) = Marshal.pack v
+   unpack = Cons . Marshal.unpack
+
+instance (TypeNum.Positive n, Storable a) => Storable (T n a) where
+   sizeOf (Cons v) = Store.sizeOf v
+   alignment (Cons v) = Store.alignment v
+   poke ptr (Cons v) = Store.poke (castPtr ptr) v
+   peek ptr = Cons <$> Store.peek (castPtr ptr)
+
+instance
+   (TypeNum.Positive n, Storable.Vector a, MultiVector.C a) =>
+      Storable.C (T n a) where
+   load ptr = fmap fromOrdinary $ Storable.load =<< LLVM.bitcast ptr
+   store v ptr = Storable.store (toOrdinary v) =<< LLVM.bitcast ptr
+
+instance
+   (TypeNum.Positive n, MultiVector.IntegerConstant a) =>
+      MultiValue.IntegerConstant (T n a) where
+   fromInteger' = fromMultiVector . MultiVector.fromInteger'
+
+instance
+   (TypeNum.Positive n, MultiVector.RationalConstant a) =>
+      MultiValue.RationalConstant (T n a) where
+   fromRational' = fromMultiVector . MultiVector.fromRational'
+
+instance
+   (TypeNum.Positive n, MultiVector.Additive a) =>
+      MultiValue.Additive (T n a) where
+   add = lift2 MultiVector.add
+   sub = lift2 MultiVector.sub
+   neg = lift1 MultiVector.neg
+
+instance
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+      MultiValue.PseudoRing (T n a) where
+   mul = lift2 MultiVector.mul
+
+scale ::
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   MultiValue.T a -> Value n a -> LLVM.CodeGenFunction r (Value n a)
+scale = lift1 . MultiVector.scale
+
+instance
+   (TypeNum.Positive n, MultiVector.Real a) =>
+      MultiValue.Real (T n a) where
+   min = lift2 MultiVector.min
+   max = lift2 MultiVector.max
+   abs = lift1 MultiVector.abs
+   signum = lift1 MultiVector.signum
+
+instance
+   (TypeNum.Positive n, MultiVector.Fraction a) =>
+      MultiValue.Fraction (T n a) where
+   truncate = lift1 MultiVector.truncate
+   fraction = lift1 MultiVector.fraction
+
+instance
+   (TypeNum.Positive n, MultiVector.Field a) =>
+      MultiValue.Field (T n a) where
+   fdiv = lift2 MultiVector.fdiv
+
+instance
+   (TypeNum.Positive n, MultiVector.Algebraic a) =>
+      MultiValue.Algebraic (T n a) where
+   sqrt = lift1 MultiVector.sqrt
+
+instance
+   (TypeNum.Positive n, MultiVector.Transcendental a) =>
+      MultiValue.Transcendental (T n a) where
+   pi  = fmap fromMultiVector MultiVector.pi
+   sin = lift1 MultiVector.sin
+   log = lift1 MultiVector.log
+   exp = lift1 MultiVector.exp
+   cos = lift1 MultiVector.cos
+   pow = lift2 MultiVector.pow
+
+instance
+   (TypeNum.Positive n, n ~ m,
+    MultiVector.NativeInteger n a ar,
+    MultiValue.NativeInteger a ar) =>
+      MultiValueVec.NativeInteger (T n a) (LLVM.Vector m ar) where
+
+instance
+   (TypeNum.Positive n, n ~ m,
+    MultiVector.NativeFloating n a ar,
+    MultiValue.NativeFloating a ar) =>
+      MultiValueVec.NativeFloating (T n a) (LLVM.Vector m ar) where
+
+lift1 ::
+   (Functor f) =>
+   (MultiVector.T n a -> f (MultiVector.T m b)) ->
+   (Value n a -> f (Value m b))
+lift1 f a = fromMultiVector <$> f (toMultiVector a)
+
+lift2 ::
+   (Functor f) =>
+   (MultiVector.T n a -> MultiVector.T m b -> f (MultiVector.T k c)) ->
+   (Value n a -> Value m b -> f (Value k c))
+lift2 f a b = fromMultiVector <$> f (toMultiVector a) (toMultiVector b)
+
+
+extract ::
+   (TypeNum.Positive n,
+    MultiVector.C x, MultiValue.T x ~ a, Value n x ~ v) =>
+   LLVM.Value Word32 -> v -> LLVM.CodeGenFunction r a
+extract i v = MultiVector.extract i (toMultiVector v)
+
+insert ::
+   (TypeNum.Positive n,
+    MultiVector.C x, MultiValue.T x ~ a, Value n x ~ v) =>
+   LLVM.Value Word32 -> a -> v -> LLVM.CodeGenFunction r v
+insert i a v =
+    fromMultiVector <$> MultiVector.insert i a (toMultiVector v)
+
+modify ::
+   (TypeNum.Positive n,
+    MultiVector.C x, MultiValue.T x ~ a, Value n x ~ v) =>
+   LLVM.Value Word32 ->
+   (a -> LLVM.CodeGenFunction r a) ->
+   v -> LLVM.CodeGenFunction r v
+modify k f v = flip (insert k) v =<< f =<< extract k v
+
+
+assemble ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   [MultiValue.T a] ->
+   LLVM.CodeGenFunction r (Value n a)
+assemble = fmap fromMultiVector . MultiVector.assemble
+
+dissect ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Value n a ->
+   LLVM.CodeGenFunction r [MultiValue.T a]
+dissect = MultiVector.dissect . toMultiVector
+
+assemble1 ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   NonEmpty.T [] (MultiValue.T a) ->
+   LLVM.CodeGenFunction r (Value n a)
+assemble1 = fmap fromMultiVector . MultiVector.assemble1
+
+dissect1 ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Value n a ->
+   LLVM.CodeGenFunction r (NonEmpty.T [] (MultiValue.T a))
+dissect1 = MultiVector.dissect1 . toMultiVector
+
+
+sizeS :: TypeNum.Positive n => Value n a -> TypeNum.Singleton n
+sizeS _ = TypeNum.singleton
+
+size :: (TypeNum.Positive n, P.Integral i) => Value n a -> i
+size = TypeNum.integralFromSingleton . sizeS
+
+
+last ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Value n a -> LLVM.CodeGenFunction r (MultiValue.T a)
+last v = extract (LLVM.valueOf (size v - 1 :: Word32)) v
+
+subsample ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Value n a -> LLVM.CodeGenFunction r (MultiValue.T a)
+subsample = extract (A.zero :: LLVM.Value Word32)
+
+upsample ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   MultiValue.T a -> LLVM.CodeGenFunction r (Value n a)
+upsample = fmap fromOrdinary . MultiValueVec.replicate
+
+
+reverse ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Value n a -> LLVM.CodeGenFunction r (Value n a)
+reverse =
+   fmap fromMultiVector . MultiVector.reverse . toMultiVector
+
+shiftUp ::
+   (TypeNum.Positive n, MultiVector.C x,
+    MultiValue.T x ~ a, Value n x ~ v) =>
+   a -> v -> LLVM.CodeGenFunction r (a, v)
+shiftUp a v =
+   mapSnd fromMultiVector <$> MultiVector.shiftUp a (toMultiVector v)
+
+shiftUpMultiZero ::
+   (TypeNum.Positive n, MultiVector.C x, Value n x ~ v) =>
+   Int -> v -> LLVM.CodeGenFunction r v
+shiftUpMultiZero k v =
+   fromMultiVector <$> MultiVector.shiftUpMultiZero k (toMultiVector v)
+
+shiftDown ::
+   (TypeNum.Positive n, MultiVector.C x,
+    MultiValue.T x ~ a, Value n x ~ v) =>
+   a -> v -> LLVM.CodeGenFunction r (a, v)
+shiftDown a v =
+   mapSnd fromMultiVector <$> MultiVector.shiftDown a (toMultiVector v)
+
+
+iterate ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   (MultiValue.T a -> LLVM.CodeGenFunction r (MultiValue.T a)) ->
+   MultiValue.T a -> LLVM.CodeGenFunction r (Value n a)
+iterate f = fmap fromOrdinary . MultiValueVec.iterate f
+
+cumulate ::
+   (TypeNum.Positive n, MultiVector.Additive a) =>
+   MultiValue.T a -> Value n a ->
+   LLVM.CodeGenFunction r (MultiValue.T a, Value n a)
+cumulate a =
+   fmap (mapSnd fromMultiVector) . MultiVector.cumulate a . toMultiVector
+
+
+fromOrdinary :: MultiValue.T (LLVM.Vector n a) -> Value n a
+fromOrdinary = MultiValue.cast
+
+toOrdinary :: Value n a -> MultiValue.T (LLVM.Vector n a)
+toOrdinary = MultiValue.cast
+
+fromMultiVector :: MultiVector.T n a -> Value n a
+fromMultiVector = fromOrdinary . MultiVectorInst.toMultiValue
+
+toMultiVector :: Value n a -> MultiVector.T n a
+toMultiVector = MultiVectorInst.fromMultiValue . toOrdinary
diff --git a/src/Synthesizer/LLVM/Frame/SerialVector/Plain.hs b/src/Synthesizer/LLVM/Frame/SerialVector/Plain.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Frame/SerialVector/Plain.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE TypeFamilies #-}
+{- |
+A special vector type that represents a time-sequence of samples.
+This way we can distinguish safely between LLVM vectors
+used for parallel signals and pipelines and
+those used for chunky processing of scalar signals.
+For the chunky processing this data type allows us
+to derive the factor from the type
+that time constants have to be multiplied with.
+-}
+module Synthesizer.LLVM.Frame.SerialVector.Plain (
+   T(Cons),
+   fromList,
+   replicate,
+   iterate,
+   ) where
+
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Code
+import Synthesizer.LLVM.Frame.SerialVector.Code (T)
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Data.NonEmpty.Class as NonEmptyC
+import qualified Data.NonEmpty as NonEmpty
+
+import Prelude as P hiding (zip, unzip, last, reverse, iterate, replicate)
+
+
+fromList :: (TypeNum.Positive n) => NonEmpty.T [] a -> T n a
+fromList = Code.Cons . LLVM.cyclicVector
+
+replicate :: (TypeNum.Positive n) => a -> T n a
+replicate = Code.Cons . pure
+
+iterate :: (TypeNum.Positive n) => (a -> a) -> a -> T n a
+iterate f x = fromList $ NonEmptyC.iterate f x
diff --git a/src/Synthesizer/LLVM/Frame/Stereo.hs b/src/Synthesizer/LLVM/Frame/Stereo.hs
--- a/src/Synthesizer/LLVM/Frame/Stereo.hs
+++ b/src/Synthesizer/LLVM/Frame/Stereo.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 {- |
 Re-export functions from "Sound.Frame.Stereo"
@@ -9,7 +10,11 @@
 -}
 module Synthesizer.LLVM.Frame.Stereo (
    Stereo.T, Stereo.cons, Stereo.left, Stereo.right,
-   Stereo.Channel(Left, Right), Stereo.select,
+   Stereo.Channel(Stereo.Left, Stereo.Right), Stereo.select,
+   Stereo.swap,
+   multiValue, unMultiValue, consMultiValue, unExpression,
+   multiVector, unMultiVector,
+   multiValueSerial, unMultiValueSerial,
    Stereo.arrowFromMono,
    Stereo.arrowFromMonoControlled,
    Stereo.arrowFromChannels,
@@ -18,22 +23,31 @@
    Stereo.liftApplicative,
    ) where
 
+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
 import qualified Synthesizer.Frame.Stereo as Stereo
 
-import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.DSL.Expression as Expr
+import qualified LLVM.DSL.Value as Value
+
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value.Storable as StorableMV
+import qualified LLVM.Extra.Multi.Value.Marshal as MarshalMV
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Storable as Storable
 import qualified LLVM.Extra.Marshal as Marshal
 import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Control as C
 import qualified LLVM.Extra.Vector as Vector
 import qualified LLVM.Core as LLVM
 
 import Type.Data.Num.Decimal (d0, d1)
 
-import Control.Monad (liftM2)
-import Control.Applicative (liftA2)
+import Control.Applicative (liftA2, pure, (<$>))
+
 import qualified Data.Traversable as Trav
+import qualified Data.Foldable as Fold
 
 import Prelude hiding (Either(Left, Right), sequence)
 
@@ -47,38 +61,104 @@
 instance (C.Select a) => C.Select (Stereo.T a) where
    select = C.selectTraversable
 
-{-
-instance LLVM.CmpRet a, LLVM.CmpResult a ~ b => LLVM.CmpRet (Stereo.T a) (Stereo.T b) where
--}
-
 instance (Tuple.Value h) => Tuple.Value (Stereo.T h) where
    type ValueOf (Stereo.T h) = Stereo.T (Tuple.ValueOf h)
-   valueOf s =
-      Stereo.cons
-         (Tuple.valueOf $ Stereo.left s)
-         (Tuple.valueOf $ Stereo.right s)
-
-{-
-instance Tuple.Value a => Tuple.Value (Stereo.T a) where
-   buildTuple f =
-      liftM2 Stereo.cons (buildTuple f) (buildTuple f)
-
-instance IsTuple a => IsTuple (Stereo.T a) where
-   tupleDesc s =
-      tupleDesc (Stereo.left s) ++
-      tupleDesc (Stereo.right s)
--}
+   valueOf = fmap Tuple.valueOf
 
 instance (Tuple.Phi a) => Tuple.Phi (Stereo.T a) where
    phi bb v =
-      liftM2 Stereo.cons
+      liftA2 Stereo.cons
          (Tuple.phi bb (Stereo.left v))
          (Tuple.phi bb (Stereo.right v))
    addPhi bb x y = do
       Tuple.addPhi bb (Stereo.left  x) (Stereo.left  y)
       Tuple.addPhi bb (Stereo.right x) (Stereo.right y)
 
+instance (MultiValue.C a) => MultiValue.C (Stereo.T a) where
+   type Repr (Stereo.T a) = Stereo.T (MultiValue.Repr a)
+   cons = multiValue . fmap MultiValue.cons
+   undef = multiValue $ pure MultiValue.undef
+   zero = multiValue $ pure MultiValue.zero
+   phi bb = fmap multiValue . Trav.traverse (MultiValue.phi bb) . unMultiValue
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb) (unMultiValue a) (unMultiValue b)
 
+instance (MultiValue.Compose a) => MultiValue.Compose (Stereo.T a) where
+   type Composed (Stereo.T a) = Stereo.T (MultiValue.Composed a)
+   compose = multiValue . fmap MultiValue.compose
+
+instance (MultiValue.Decompose p) => MultiValue.Decompose (Stereo.T p) where
+   decompose p = liftA2 MultiValue.decompose p . unMultiValue
+
+type instance MultiValue.Decomposed f (Stereo.T pa) =
+                  Stereo.T (MultiValue.Decomposed f pa)
+type instance MultiValue.PatternTuple (Stereo.T pa) =
+                  Stereo.T (MultiValue.PatternTuple pa)
+
+multiValue :: Stereo.T (MultiValue.T a) -> MultiValue.T (Stereo.T a)
+multiValue = MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
+
+unMultiValue :: MultiValue.T (Stereo.T a) -> Stereo.T (MultiValue.T a)
+unMultiValue (MultiValue.Cons x) = fmap MultiValue.Cons x
+
+consMultiValue :: MultiValue.T a -> MultiValue.T a -> MultiValue.T (Stereo.T a)
+consMultiValue l r = multiValue $ Stereo.cons l r
+
+
+unExpression :: Expr.Exp (Stereo.T a) -> Stereo.T (Expr.Exp a)
+unExpression x =
+   Stereo.cons
+      (Expr.lift1 (MultiValue.lift1 Stereo.left) x)
+      (Expr.lift1 (MultiValue.lift1 Stereo.right) x)
+
+
+instance (MultiVector.C a) => MultiVector.C (Stereo.T a) where
+   type Repr n (Stereo.T a) = Stereo.T (MultiVector.Repr n a)
+   cons = multiVector . fmap MultiVector.cons . Stereo.sequence
+   undef = multiVector $ pure MultiVector.undef
+   zero = multiVector $ pure MultiVector.zero
+   phi bb =
+      fmap multiVector . Trav.traverse (MultiVector.phi bb) . unMultiVector
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiVector.addPhi bb) (unMultiVector a) (unMultiVector b)
+
+   shuffle is u v =
+      multiVector <$>
+      traverse2 (MultiVector.shuffle is) (unMultiVector u) (unMultiVector v)
+   extract k =
+      fmap multiValue . Trav.traverse (MultiVector.extract k) . unMultiVector
+   insert k a v =
+      multiVector <$>
+      traverse2 (MultiVector.insert k) (unMultiValue a) (unMultiVector v)
+
+multiVector :: Stereo.T (MultiVector.T n a) -> MultiVector.T n (Stereo.T a)
+multiVector = MultiVector.Cons . fmap (\(MultiVector.Cons a) -> a)
+
+unMultiVector :: MultiVector.T n (Stereo.T a) -> Stereo.T (MultiVector.T n a)
+unMultiVector (MultiVector.Cons x) = fmap MultiVector.Cons x
+
+
+multiValueSerial ::
+   Stereo.T (MultiValue.T (Serial.T n a)) ->
+   MultiValue.T (Serial.T n (Stereo.T a))
+multiValueSerial = MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
+
+unMultiValueSerial ::
+   MultiValue.T (Serial.T n (Stereo.T a)) ->
+   Stereo.T (MultiValue.T (Serial.T n a))
+unMultiValueSerial (MultiValue.Cons x) = fmap MultiValue.Cons x
+
+
+instance
+      (Expr.Aggregate e mv) => Expr.Aggregate (Stereo.T e) (Stereo.T mv) where
+   type MultiValuesOf (Stereo.T e) = Stereo.T (Expr.MultiValuesOf e)
+   type ExpressionsOf (Stereo.T mv) = Stereo.T (Expr.ExpressionsOf mv)
+   bundle = Trav.traverse Expr.bundle
+   dissect = fmap Expr.dissect
+
+
 instance (Vector.Simple v) => Vector.Simple (Stereo.T v) where
    type Element (Stereo.T v) = Stereo.T (Vector.Element v)
    type Size (Stereo.T v) = Vector.Size v
@@ -114,13 +194,31 @@
    load = Storable.loadApplicative
    store = Storable.storeFoldable
 
+instance (MarshalMV.C l) => MarshalMV.C (Stereo.T l) where
+   pack x = MarshalMV.pack (Stereo.left x, Stereo.right x)
+   unpack = uncurry Stereo.cons . MarshalMV.unpack
 
+instance (StorableMV.C l) => StorableMV.C (Stereo.T l) where
+   load = StorableMV.loadApplicative
+   store = StorableMV.storeFoldable
+
+instance
+   (StorableMV.Vector l, MultiVector.C l) =>
+      StorableMV.Vector (Stereo.T l) where
+   assembleVector p =
+      Trav.traverse (StorableMV.assembleVector (Stereo.left<$>p)) .
+      Stereo.sequence
+   disassembleVector p =
+      fmap (\x -> liftA2 Stereo.cons (Stereo.left x) (Stereo.right x)) .
+      Trav.traverse (StorableMV.disassembleVector (Stereo.left<$>p))
+
+
 {-
 instance
       (Memory l s) =>
       Memory (Stereo.T l) (LLVM.Struct (s, (s, ()))) where
    load ptr =
-      liftM2 Stereo.cons
+      liftA2 Stereo.cons
          (load =<< getElementPtr0 ptr (d0, ()))
          (load =<< getElementPtr0 ptr (d1, ()))
    store y ptr = do
@@ -130,11 +228,33 @@
 
 instance (A.Additive a) => A.Additive (Stereo.T a) where
    zero = Stereo.cons A.zero A.zero
-   add x y = Trav.sequence $ liftA2 A.add x y
-   sub x y = Trav.sequence $ liftA2 A.sub x y
-   neg x   = Trav.sequence $ fmap A.neg x
+   add x y = traverse2 A.add x y
+   sub x y = traverse2 A.sub x y
+   neg x   = Trav.traverse A.neg x
 
 type instance A.Scalar (Stereo.T a) = A.Scalar a
 
 instance (A.PseudoModule a) => A.PseudoModule (Stereo.T a) where
-   scale a = Trav.sequence . fmap (A.scale a)
+   scale a = Trav.traverse (A.scale a)
+
+
+
+instance (MultiValue.Additive a) => MultiValue.Additive (Stereo.T a) where
+   add x y =
+      multiValue <$> traverse2 MultiValue.add (unMultiValue x) (unMultiValue y)
+   sub x y =
+      multiValue <$> traverse2 MultiValue.sub (unMultiValue x) (unMultiValue y)
+   neg x = multiValue <$> Trav.traverse MultiValue.neg (unMultiValue x)
+
+
+traverse2 ::
+   (Monad m, Applicative t, Traversable t) =>
+   (a -> b -> m c) -> t a -> t b -> m (t c)
+traverse2 f x y = Trav.sequence $ liftA2 f x y
+
+
+
+instance Value.Flatten a => Value.Flatten (Stereo.T a) where
+   type Registers (Stereo.T a) = Stereo.T (Value.Registers a)
+   flattenCode = Value.flattenCodeTraversable
+   unfoldCode = Value.unfoldCodeTraversable
diff --git a/src/Synthesizer/LLVM/Frame/StereoInterleaved.hs b/src/Synthesizer/LLVM/Frame/StereoInterleaved.hs
--- a/src/Synthesizer/LLVM/Frame/StereoInterleaved.hs
+++ b/src/Synthesizer/LLVM/Frame/StereoInterleaved.hs
@@ -1,332 +1,45 @@
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{- |
-Represent a vector of Stereo values in two vectors
-that store the values in an interleaved way.
-That is:
-
-> vector0[0] = left[0]
-> vector0[1] = right[0]
-> vector0[2] = left[1]
-> vector0[3] = right[1]
-> vector1[0] = left[2]
-> vector1[1] = right[2]
-> vector1[2] = left[3]
-> vector1[3] = right[3]
-
-This representation is not very useful for computation,
-but necessary as intermediate representation for interfacing with memory.
-SSE/SSE2 have the instructions UNPACK(L|H)P(S|D) that interleave efficiently.
--}
 module Synthesizer.LLVM.Frame.StereoInterleaved (
    T,
-   Value(Value),
+   Value,
    interleave,
    deinterleave,
-   fromMono,
-   assemble, extractAll,
-   zero,
    amplify,
    envelope,
    ) where
 
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
-
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Control as C
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Core as LLVM
-import LLVM.Core (Vector, IsSized, SizeOf)
-
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import qualified Foreign.Storable as St
-import Foreign.Ptr (Ptr, castPtr)
-
-import qualified Data.Foldable as Fold
-import Control.Monad (liftM2)
-import Control.Applicative (liftA2, pure)
-
-import Data.Tuple.HT (mapPair)
-
-import qualified Algebra.Additive as Additive
-
-
-data T n a = Cons (Vector n a) (Vector n a)
-
-data Value n a = Value (LLVM.Value (Vector n a)) (LLVM.Value (Vector n a))
+import qualified Synthesizer.LLVM.Frame.StereoInterleavedCode as StereoInt
+import Synthesizer.LLVM.Frame.StereoInterleavedCode (T, Value)
 
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
 
-type instance F.Arguments f (Value n a) = f (Value n a)
-instance F.MakeArguments (Value n a) where
-   makeArgs = id
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
 
+import qualified LLVM.Extra.Multi.Vector as MultiVector
 
-withSize :: (TypeNum.Natural n) => (Int -> m (Value n a)) -> m (Value n a)
-withSize =
-   let sz ::
-          (TypeNum.Natural n) =>
-          TypeNum.Singleton n -> (Int -> m (Value n a)) -> m (Value n a)
-       sz n f = f (TypeNum.integralFromSingleton n)
-   in  sz TypeNum.singleton
+import qualified Type.Data.Num.Decimal as TypeNum
 
 
 interleave ::
-   (LLVM.IsPrimitive a, TypeNum.Positive n) =>
-   Stereo.T (Serial.Value n a) ->
-   LLVM.CodeGenFunction r (Value n a)
-interleave x =
-   assemble =<< Serial.extractAll x
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Stereo.T (Exp (Serial.T n a)) -> Exp (T n a)
+interleave = Expr.liftM StereoInt.interleave
 
 deinterleave ::
-   (LLVM.IsPrimitive a, TypeNum.Positive n) =>
-   Value n a ->
-   LLVM.CodeGenFunction r (Stereo.T (Serial.Value n a))
-deinterleave v =
-   Serial.assemble =<< extractAll v
-
-fromMono ::
-   (LLVM.IsPrimitive a, TypeNum.Positive n) =>
-   Serial.Value n a ->
-   LLVM.CodeGenFunction r (Value n a)
-fromMono x =
-   assemble . map pure =<< Serial.extractAll x
-
-assemble ::
-   (LLVM.IsPrimitive a, TypeNum.Positive n) =>
-   [Stereo.T (LLVM.Value a)] -> LLVM.CodeGenFunction r (Value n a)
-assemble x =
-   withSize $ \n ->
-      uncurry (liftM2 Value) .
-      mapPair (Vector.assemble, Vector.assemble) .
-      splitAt n .
-      concatMap Fold.toList $ x
-
-extractAll ::
-   (LLVM.IsPrimitive a, TypeNum.Positive n) =>
-   Value n a -> LLVM.CodeGenFunction r [Stereo.T (LLVM.Value a)]
-extractAll (Value v0 v1) =
-   fmap
-      (let aux (l:r:xs) = Stereo.cons l r : aux xs
-           aux [] = []
-           aux _ = error "odd number of stereo elements"
-       in  aux) $
-   liftM2 (++)
-      (Vector.extractAll v0)
-      (Vector.extractAll v1)
-
-
-instance
-   (TypeNum.Positive n, LLVM.IsPrimitive a, St.Storable a) =>
-      St.Storable (T n a) where
-   sizeOf ~(Cons v0 v1) = St.sizeOf v0 + St.sizeOf v1
-   alignment ~(Cons v _) = St.alignment v
-   peek ptr =
-      let p = castPtr ptr
-      in  liftM2 Cons
-             (St.peekElemOff p 0)
-             (St.peekElemOff p 1)
-   poke ptr (Cons v0 v1) =
-      let p = castPtr ptr
-      in  St.pokeElemOff p 0 v0 >>
-          St.pokeElemOff p 1 v1
-
-instance (TypeNum.Positive n, LLVM.IsPrimitive a) => Tuple.Zero (Value n a) where
-   zero = Value Tuple.zero Tuple.zero
-
-instance (TypeNum.Positive n, LLVM.IsPrimitive a) => Tuple.Undefined (Value n a) where
-   undef = Value (LLVM.value LLVM.undef) (LLVM.value LLVM.undef)
-
-{-
-Can only be implemented by ifThenElse
-since the atomic 'select' command wants a bool vector.
-
-instance (TypeNum.Positive n, LLVM.IsPrimitive a, Tuple.Phi a) => C.Select (Value n a) where
-   select b (Value x0 x1) (Value y0 y1) =
-      liftM2 Value
-         (C.select b x0 y0)
-         (C.select b x1 y1)
-
-instance LLVM.CmpRet a, LLVM.CmpResult a ~ b => LLVM.CmpRet (Stereo.T a) (Stereo.T b) where
--}
-
-instance (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsConst a) =>
-      Tuple.Value (T n a) where
-   type ValueOf (T n a) = Value n a
-   valueOf (Cons v0 v1) =
-      Value
-         (LLVM.valueOf v0)
-         (LLVM.valueOf v1)
-
-instance (TypeNum.Positive n, LLVM.IsPrimitive a) => Tuple.Phi (Value n a) where
-   phi bb = mapV (Tuple.phi bb)
-   addPhi bb = zipV (\_ _ -> ()) (Tuple.addPhi bb)
-
-
-instance (TypeNum.Positive n) => Serial.Sized (Value n a) where
-   type Size (Value n a) = n
-
-{- |
-The implementation of 'extract' may need to perform
-arithmetics at run-time and is thus a bit inefficient.
--}
-instance (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsFirstClass a) => Serial.Read (Value n a) where
-   type Element (Value n a) = Stereo.T (LLVM.Value a)
-   type ReadIt (Value n a) = Value n a
-
-   extract k (Value v0 v1) =
-      let size = LLVM.valueOf $ fromIntegral $ Vector.sizeInTuple v0
-          ext j = do
-             b <- A.cmp LLVM.CmpLT j size
-             C.ifThenElse b
-                (Vector.extract j v0)
-                (do j1 <- A.sub j size
-                    Vector.extract j1 v1)
-      in  do
-             k20 <- A.add k k
-             k21 <- A.inc k20
-             liftM2 Stereo.cons (ext k20) (ext k21)
-
-   extractAll = extractAll
-
-   readStart = return . Serial.Iterator
-   readNext (Serial.Iterator v) = do
-      xt <- extractAll v
-      case xt of
-         x:xs -> fmap ((,) x . Serial.Iterator) $ assemble xs
-         [] -> error "StereoInterleaved.readNext: size zero"
-
-
-{- |
-The implementation of 'insert' may need to perform
-arithmetics at run-time and is thus a bit inefficient.
--}
-instance (TypeNum.Positive n, LLVM.IsPrimitive a) => Serial.C (Value n a) where
-   type WriteIt (Value n a) = Value n a
-
-   insert k x v =
-      let size = LLVM.valueOf $ fromIntegral $ Serial.size v
-          ins j c (Value v0 v1) = do
-             b <- A.cmp LLVM.CmpLT j size
-             C.ifThenElse b
-                (do w0 <- Vector.insert j c v0
-                    return $ Value w0 v1)
-                (do j1 <- A.sub j size
-                    w1 <- Vector.insert j1 c v1
-                    return $ Value v0 w1)
-      in  do
-             k20 <- A.add k k
-             k21 <- A.inc k20
-             ins k21 (Stereo.right x) =<< ins k20 (Stereo.left x) v
-
-   assemble = assemble
-
-   writeStart = return (Serial.Iterator Tuple.undef)
-   writeNext x (Serial.Iterator v) = do
-      xs <- extractAll v
-      fmap Serial.Iterator $ assemble $ tail xs ++ [x]
-   writeStop (Serial.Iterator v) = return v
-
-
-type Struct n a = LLVM.Struct (Vector n a, (Vector n a, ()))
-
-memory ::
-   (TypeNum.Positive n, LLVM.IsPrimitive a, IsSized a,
-    TypeNum.Positive (n TypeNum.:*: SizeOf a)) =>
-   Memory.Record r (Struct n a) (Value n a)
-memory =
-   liftA2 Value
-      (Memory.element (\(Value v _) -> v) TypeNum.d0)
-      (Memory.element (\(Value _ v) -> v) TypeNum.d1)
-
-instance
-      (TypeNum.Positive n,
-       LLVM.IsPrimitive a, IsSized a,
-       TypeNum.Positive (n TypeNum.:*: SizeOf a)) =>
-      Memory.C (Value n a) where
-   type Struct (Value n a) = Struct n a
-   load = Memory.loadRecord memory
-   store = Memory.storeRecord memory
-   decompose = Memory.decomposeRecord memory
-   compose = Memory.composeRecord memory
-
-instance
-   (TypeNum.Positive n, Tuple.VectorValue n a,
-    Tuple.VectorValueOf n a ~ LLVM.Value (Vector n a),
-    LLVM.IsPrimitive a, LLVM.IsConst a, Storable.Vector a) =>
-      Storable.C (T n a) where
-   load ptrV = do
-      ptr <- castHalfPtr ptrV
-      liftM2 Value
-         (Storable.load ptr)
-         (Storable.load =<< Storable.incrementPtr ptr)
-   store (Value v0 v1) ptrV = do
-      ptr <- castHalfPtr ptrV
-      Storable.storeNext v0 ptr >>= Storable.store v1
-
-castHalfPtr ::
-   LLVM.Value (Ptr (T n a)) ->
-   LLVM.CodeGenFunction r (LLVM.Value (Ptr (Vector n a)))
-castHalfPtr = LLVM.bitcast
-
-
-{- |
-This instance allows to run @arrange@ on interleaved stereo vectors.
--}
-instance
-   (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>
-      A.Additive (Value n a) where
-   zero = Value A.zero A.zero
-   add = zipV Value A.add
-   sub = zipV Value A.sub
-   neg = mapV A.neg
-
-
-zero :: (TypeNum.Positive n, Additive.C a) => (T n a)
-zero = Cons (pure Additive.zero) (pure Additive.zero)
-
-
-scale ::
-   (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>
-   LLVM.Value a -> Value n a -> LLVM.CodeGenFunction r (Value n a)
-scale a v = do
-   av <- SoV.replicate a
-   mapV (A.mul av) v
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Exp (T n a) -> Stereo.T (Exp (Serial.T n a))
+deinterleave x =
+   Stereo.cons
+      (Expr.liftM (fmap Stereo.left  . StereoInt.deinterleave) x)
+      (Expr.liftM (fmap Stereo.right . StereoInt.deinterleave) x)
 
 amplify ::
-   (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsArithmetic a, LLVM.IsConst a) =>
-   a -> Value n a -> LLVM.CodeGenFunction r (Value n a)
-amplify a = scale (LLVM.valueOf a)
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   Exp a -> Exp (T n a) -> Exp (T n a)
+amplify = Expr.liftM2 StereoInt.scale
 
 envelope ::
-   (TypeNum.Positive n, LLVM.IsPrimitive a, LLVM.IsArithmetic a, LLVM.IsConst a) =>
-   Serial.Value n a -> Value n a -> LLVM.CodeGenFunction r (Value n a)
-envelope e a =
-   zipV Value (flip A.mul) a =<< fromMono e
-
-
-mapV :: (Monad m) =>
-   (LLVM.Value (Vector n a) -> m (LLVM.Value (Vector n a))) ->
-   Value n a -> m (Value n a)
-mapV f (Value x0 x1) =
-   liftM2 Value (f x0) (f x1)
-
-zipV :: (Monad m) =>
-   (c -> c -> d) ->
-   (LLVM.Value (Vector n a) ->
-    LLVM.Value (Vector n b) ->
-    m c) ->
-   Value n a ->
-   Value n b ->
-   m d
-zipV g f (Value x0 x1) (Value y0 y1) =
-   liftM2 g (f x0 y0) (f x1 y1)
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   Exp (Serial.T n a) -> Exp (T n a) -> Exp (T n a)
+envelope = Expr.liftM2 StereoInt.envelope
diff --git a/src/Synthesizer/LLVM/Frame/StereoInterleavedCode.hs b/src/Synthesizer/LLVM/Frame/StereoInterleavedCode.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Frame/StereoInterleavedCode.hs
@@ -0,0 +1,241 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{- |
+Represent a vector of Stereo values in two vectors
+that store the values in an interleaved way.
+That is:
+
+> vector0[0] = left[0]
+> vector0[1] = right[0]
+> vector0[2] = left[1]
+> vector0[3] = right[1]
+> vector1[0] = left[2]
+> vector1[1] = right[2]
+> vector1[2] = left[3]
+> vector1[3] = right[3]
+
+This representation is not very useful for computation,
+but necessary as intermediate representation for interfacing with memory.
+SSE/SSE2 have the instructions UNPACK(L|H)P(S|D) that interleave efficiently.
+-}
+module Synthesizer.LLVM.Frame.StereoInterleavedCode (
+   T,
+   Value,
+   interleave,
+   deinterleave,
+   fromMono,
+   assemble, dissect,
+   zero,
+   scale,
+   amplify,
+   envelope,
+   ) where
+
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
+
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Core as LLVM
+import LLVM.Core (Vector)
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Foreign.Storable as St
+import Foreign.Ptr (Ptr, castPtr)
+
+import qualified Control.Applicative.HT as AppHT
+import Control.Applicative (liftA2, pure)
+
+import qualified Data.Foldable as Fold
+import Data.Tuple.HT (mapPair)
+
+import qualified Algebra.Additive as Additive
+
+
+data T n a = Cons (Vector n a) (Vector n a)
+
+type Value n a = MultiValue.T (T n a)
+
+
+withSize :: (TypeNum.Natural n) => (Int -> m (Value n a)) -> m (Value n a)
+withSize =
+   let sz ::
+          (TypeNum.Natural n) =>
+          TypeNum.Singleton n -> (Int -> m (Value n a)) -> m (Value n a)
+       sz n f = f (TypeNum.integralFromSingleton n)
+   in  sz TypeNum.singleton
+
+
+interleave ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Stereo.T (Serial.Value n a) ->
+   LLVM.CodeGenFunction r (Value n a)
+interleave x =
+   assemble . map Stereo.unMultiValue
+      =<< Serial.dissect (Stereo.multiValueSerial x)
+
+deinterleave ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Value n a ->
+   LLVM.CodeGenFunction r (Stereo.T (Serial.Value n a))
+deinterleave v =
+   Stereo.unMultiValueSerial <$>
+      (Serial.assemble . map Stereo.multiValue =<< dissect v)
+
+fromMono ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Serial.Value n a ->
+   LLVM.CodeGenFunction r (Value n a)
+fromMono x =
+   assemble . map pure =<< Serial.dissect x
+
+assemble ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   [Stereo.T (MultiValue.T a)] -> LLVM.CodeGenFunction r (Value n a)
+assemble x =
+   withSize $ \n ->
+      uncurry (liftA2 merge) .
+      mapPair (MultiVector.assemble, MultiVector.assemble) .
+      splitAt n .
+      concatMap Fold.toList $ x
+
+dissect ::
+   (TypeNum.Positive n, MultiVector.C a) =>
+   Value n a -> LLVM.CodeGenFunction r [Stereo.T (MultiValue.T a)]
+dissect v =
+   let (v0,v1) = split v in
+   fmap
+      (let aux (l:r:xs) = Stereo.cons l r : aux xs
+           aux [] = []
+           aux _ = error "odd number of stereo elements"
+       in  aux) $
+   liftA2 (++)
+      (MultiVector.dissect v0)
+      (MultiVector.dissect v1)
+
+
+merge :: MultiVector.T n a -> MultiVector.T n a -> MultiValue.T (T n a)
+merge (MultiVector.Cons a) (MultiVector.Cons b) = MultiValue.Cons (a,b)
+
+split :: MultiValue.T (T n a) -> (MultiVector.T n a, MultiVector.T n a)
+split (MultiValue.Cons (a,b)) = (MultiVector.Cons a, MultiVector.Cons b)
+
+merge_ ::
+   MultiValue.T (Vector n a) -> MultiValue.T (Vector n a) ->
+   MultiValue.T (T n a)
+merge_ (MultiValue.Cons a) (MultiValue.Cons b) = MultiValue.Cons (a,b)
+
+split_ ::
+   MultiValue.T (T n a) ->
+   (MultiValue.T (Vector n a), MultiValue.T (Vector n a))
+split_ (MultiValue.Cons (a,b)) = (MultiValue.Cons a, MultiValue.Cons b)
+
+instance (TypeNum.Positive n, MultiVector.C a) => MultiValue.C (T n a) where
+   type Repr (T n a) = (MultiVector.Repr n a, MultiVector.Repr n a)
+   cons (Cons v0 v1) = merge (MultiVector.cons v0) (MultiVector.cons v1)
+   undef = merge MultiVector.undef MultiVector.undef
+   zero = merge MultiVector.zero MultiVector.zero
+   phi bb =
+      fmap (uncurry merge) .
+      AppHT.mapPair (MultiVector.phi bb, MultiVector.phi bb) . split
+   addPhi bb a b =
+      case (split a, split b) of
+         ((a0,a1), (b0,b1)) -> do
+            MultiVector.addPhi bb a0 b0
+            MultiVector.addPhi bb a1 b1
+
+instance (Marshal.Vector n a) => Marshal.C (T n a) where
+   pack (Cons v0 v1) = Marshal.pack (v0,v1)
+   unpack = uncurry Cons . Marshal.unpack
+
+instance
+   (TypeNum.Positive n, MultiVector.C a, St.Storable a) =>
+      St.Storable (T n a) where
+   sizeOf ~(Cons v0 v1) = St.sizeOf v0 + St.sizeOf v1
+   alignment ~(Cons v _) = St.alignment v
+   peek ptr =
+      let p = castPtr ptr
+      in  liftA2 Cons
+             (St.peekElemOff p 0)
+             (St.peekElemOff p 1)
+   poke ptr (Cons v0 v1) =
+      let p = castPtr ptr
+      in  St.pokeElemOff p 0 v0 >>
+          St.pokeElemOff p 1 v1
+
+instance (TypeNum.Positive n, Storable.Vector a) => Storable.C (T n a) where
+   load ptrV = do
+      ptr <- castHalfPtr ptrV
+      liftA2 merge_
+         (Storable.load ptr)
+         (Storable.load =<< Storable.incrementPtr ptr)
+   store v ptrV = do
+      let (v0,v1) = split_ v
+      ptr <- castHalfPtr ptrV
+      Storable.storeNext v0 ptr >>= Storable.store v1
+
+castHalfPtr ::
+   LLVM.Value (Ptr (T n a)) ->
+   LLVM.CodeGenFunction r (LLVM.Value (Ptr (Vector n a)))
+castHalfPtr = LLVM.bitcast
+
+
+{- |
+This instance allows to run @arrange@ on interleaved stereo vectors.
+-}
+instance
+   (TypeNum.Positive n, MultiVector.Additive a) =>
+      MultiValue.Additive (T n a) where
+   add = zipV merge A.add
+   sub = zipV merge A.sub
+   neg = mapV A.neg
+
+
+zero :: (TypeNum.Positive n, Additive.C a) => T n a
+zero = Cons (pure Additive.zero) (pure Additive.zero)
+
+
+scale ::
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   MultiValue.T a -> Value n a -> LLVM.CodeGenFunction r (Value n a)
+scale a v = do
+   av <- MultiVector.replicate a
+   mapV (A.mul av) v
+
+amplify ::
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   a -> Value n a -> LLVM.CodeGenFunction r (Value n a)
+amplify a = scale (MultiValue.cons a)
+
+envelope ::
+   (TypeNum.Positive n, MultiVector.PseudoRing a) =>
+   Serial.Value n a -> Value n a -> LLVM.CodeGenFunction r (Value n a)
+envelope e a =
+   zipV merge (flip A.mul) a =<< fromMono e
+
+
+mapV :: (Applicative m) =>
+   (MultiVector.T n a -> m (MultiVector.T n a)) ->
+   Value n a -> m (Value n a)
+mapV f x =
+   case split x of
+      (x0,x1) -> uncurry merge <$> liftA2 (,) (f x0) (f x1)
+
+zipV :: (Applicative m) =>
+   (c -> c -> d) ->
+   (MultiVector.T n a ->
+    MultiVector.T n b ->
+    m c) ->
+   Value n a ->
+   Value n b ->
+   m d
+zipV g f x y =
+   case (split x, split y) of
+      ((x0,x1), (y0,y1)) -> liftA2 g (f x0 y0) (f x1 y1)
diff --git a/src/Synthesizer/LLVM/Generator/Core.hs b/src/Synthesizer/LLVM/Generator/Core.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Generator/Core.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module Synthesizer.LLVM.Generator.Core where
+
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Private as Sig
+import qualified Synthesizer.LLVM.Random as Rnd
+
+import Synthesizer.Causal.Class (($*))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Arithmetic as A
+
+import Control.Applicative ((<$>))
+
+import Data.Word (Word32)
+
+import NumericPrelude.Numeric
+import NumericPrelude.Base hiding (map, iterate, takeWhile, tail)
+
+
+
+type MV a = Sig.T (MultiValue.T a)
+
+iterate :: (Marshal.C a) => (Exp a -> Exp a) -> Exp a -> MV a
+iterate f a = Sig.iterate (Expr.unliftM1 f) (Expr.unExp a)
+
+-- ToDo: replace by constantSharing and scanl
+iterateParam ::
+   (Marshal.C a, Marshal.C b) =>
+   (Exp b -> Exp a -> Exp a) -> Exp b -> Exp a -> MV a
+iterateParam f b a =
+   MultiValue.snd <$>
+   iterate (Expr.uncurry $ \bi ai -> Expr.zip bi $ f bi ai) (Expr.zip b a)
+
+
+ramp ::
+   (Marshal.C a, MultiValue.Additive a) =>
+   Exp a -> Exp a -> MV a
+ramp = iterateParam Expr.add
+
+parabola ::
+   (Marshal.C a, MultiValue.Additive a) =>
+   Exp a -> Exp a -> Exp a -> MV a
+parabola d2 d1 start = integrate start $* ramp d2 d1
+
+integrate ::
+   (Marshal.C a, MultiValue.Additive a, MultiValue.T a ~ al) =>
+   Exp a -> Causal.T al al
+integrate start =
+   Causal.mapAccum (\a s -> (,) s <$> A.add s a) (Expr.unExp start)
+
+
+osci ::
+   (MultiValue.Fraction t, Marshal.C t) =>
+   Exp t -> Exp t -> MV t
+osci phase freq  =  iterate (Expr.liftM2 A.incPhase freq) phase
+
+exponential ::
+   (Marshal.C a, MultiValue.PseudoRing a) =>
+   Exp a -> Exp a -> MV a
+exponential  =  iterateParam Expr.mul
+
+exponentialBounded ::
+   (Marshal.C a, MultiValue.PseudoRing a,
+    MultiValue.Real a, MultiValue.IntegerConstant a) =>
+   Exp a -> Exp a -> Exp a -> MV a
+exponentialBounded bound decay =
+   iterateParam
+      (\bk y -> case Expr.unzip bk of (b,k) -> Expr.max b $ k*y)
+      (Expr.zip bound decay)
+
+
+noise, noiseAlt :: Exp Word32 -> MV Word32
+noise seed =
+   iterate (Expr.liftReprM Rnd.nextCG)
+      (Expr.irem seed (Expr.cons Rnd.modulus-1) + 1)
+
+noiseAlt seed =
+   iterate (Expr.liftReprM Rnd.nextCG32)
+      (Expr.irem seed (Expr.cons Rnd.modulus-1) + 1)
diff --git a/src/Synthesizer/LLVM/Generator/Exponential2.hs b/src/Synthesizer/LLVM/Generator/Exponential2.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Generator/Exponential2.hs
+++ /dev/null
@@ -1,332 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{- |
-Exponential curve with controllable delay.
--}
-module Synthesizer.LLVM.Generator.Exponential2 (
-   Parameter,
-   parameter,
-   parameterPlain,
-   causalP,
-
-   ParameterPacked,
-   parameterPacked,
-   parameterPackedPlain,
-   causalPackedP,
-   ) where
-
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Simple.Value as Value
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.Arithmetic as A
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-         (CodeGenFunction, Value, IsArithmetic, IsPrimitive, IsFloating, SizeOf)
-
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal.Number ((:*:))
-
-import Foreign.Storable (Storable)
-import qualified Foreign.Storable
--- import qualified Foreign.Storable.Record as Store
-import qualified Foreign.Storable.Traversable as Store
-
-import qualified Control.Applicative as App
-import qualified Data.Foldable as Fold
-import qualified Data.Traversable as Trav
-import Control.Applicative (liftA2, (<*>))
-import Control.Arrow (arr, (^<<), (&&&))
-import Control.Monad (liftM2)
-
-import qualified Algebra.Transcendental as Trans
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base
-
-
-newtype Parameter a = Parameter a
-   deriving (Show, Storable)
-
-
-instance Functor Parameter where
-   {-# INLINE fmap #-}
-   fmap f (Parameter k) = Parameter (f k)
-
-instance App.Applicative Parameter where
-   {-# INLINE pure #-}
-   pure x = Parameter x
-   {-# INLINE (<*>) #-}
-   Parameter f <*> Parameter k =
-      Parameter (f k)
-
-instance Fold.Foldable Parameter where
-   {-# INLINE foldMap #-}
-   foldMap = Trav.foldMapDefault
-
-instance Trav.Traversable Parameter where
-   {-# INLINE sequenceA #-}
-   sequenceA (Parameter k) =
-      fmap Parameter k
-
-
-instance (Tuple.Phi a) => Tuple.Phi (Parameter a) where
-   phi = Tuple.phiTraversable
-   addPhi = Tuple.addPhiFoldable
-
-instance Tuple.Undefined a => Tuple.Undefined (Parameter a) where
-   undef = Tuple.undefPointed
-
-instance Tuple.Zero a => Tuple.Zero (Parameter a) where
-   zero = Tuple.zeroPointed
-
-instance (Memory.C a) => Memory.C (Parameter a) where
-   type Struct (Parameter a) = Memory.Struct a
-   load = Memory.loadNewtype Parameter
-   store = Memory.storeNewtype (\(Parameter k) -> k)
-   decompose = Memory.decomposeNewtype Parameter
-   compose = Memory.composeNewtype (\(Parameter k) -> k)
-
-instance (Storable.C a) => Storable.C (Parameter a) where
-   load = Storable.loadNewtype Parameter Parameter
-   store = Storable.storeNewtype Parameter (\(Parameter k) -> k)
-
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (Parameter a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
-
-instance LLVM.IsTuple a => LLVM.IsTuple (Parameter a) where
-   tupleDesc = Class.tupleDescFoldable
--}
-
-instance (Tuple.Value a) => Tuple.Value (Parameter a) where
-   type ValueOf (Parameter a) = Parameter (Tuple.ValueOf a)
-   valueOf = Tuple.valueOfFunctor
-
-
-instance (Value.Flatten a) => Value.Flatten (Parameter a) where
-   type Registers (Parameter a) = Parameter (Value.Registers a)
-   flattenCode = Value.flattenCodeTraversable
-   unfoldCode = Value.unfoldCodeTraversable
-
-
-instance (Vector.Simple v) => Vector.Simple (Parameter v) where
-   type Element (Parameter v) = Parameter (Vector.Element v)
-   type Size (Parameter v) = Vector.Size v
-   shuffleMatch = Vector.shuffleMatchTraversable
-   extract = Vector.extractTraversable
-
-instance (Vector.C v) => Vector.C (Parameter v) where
-   insert  = Vector.insertTraversable
-
-
-parameter ::
-   (Trans.C a, SoV.TranscendentalConstant a, IsFloating a) =>
-   Value a ->
-   CodeGenFunction r (Parameter (Value a))
-parameter = Value.unlift1 parameterPlain
-
-parameterPlain ::
-   (Trans.C a) =>
-   a -> Parameter a
-parameterPlain halfLife =
-   Parameter $ 0.5 ** recip halfLife
-
-
-causalP ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, A.PseudoRing al) =>
-   Param.T p a ->
-   CausalP.T p (Parameter al) al
-causalP initial =
-   CausalP.loop initial
-      (arr snd &&& CausalP.zipWithSimple (\(Parameter a) -> A.mul a))
-
-
-data ParameterPacked a =
-   ParameterPacked {ppFeedback, ppCurrent :: a}
-
-
-instance Functor ParameterPacked where
-   {-# INLINE fmap #-}
-   fmap f p = ParameterPacked
-      (f $ ppFeedback p) (f $ ppCurrent p)
-
-instance App.Applicative ParameterPacked where
-   {-# INLINE pure #-}
-   pure x = ParameterPacked x x
-   {-# INLINE (<*>) #-}
-   f <*> p = ParameterPacked
-      (ppFeedback f $ ppFeedback p)
-      (ppCurrent f $ ppCurrent p)
-
-instance Fold.Foldable ParameterPacked where
-   {-# INLINE foldMap #-}
-   foldMap = Trav.foldMapDefault
-
-instance Trav.Traversable ParameterPacked where
-   {-# INLINE sequenceA #-}
-   sequenceA p =
-      liftA2 ParameterPacked
-         (ppFeedback p) (ppCurrent p)
-
-
-instance (Tuple.Phi a) => Tuple.Phi (ParameterPacked a) where
-   phi = Tuple.phiTraversable
-   addPhi = Tuple.addPhiFoldable
-
-instance Tuple.Undefined a => Tuple.Undefined (ParameterPacked a) where
-   undef = Tuple.undefPointed
-
-instance Tuple.Zero a => Tuple.Zero (ParameterPacked a) where
-   zero = Tuple.zeroPointed
-
-
-{-
-storeParameter ::
-   Storable a => Store.Dictionary (ParameterPacked a)
-storeParameter =
-   Store.run $
-   liftA2 ParameterPacked
-      (Store.element ppFeedback)
-      (Store.element ppCurrent)
-
-instance Storable a => Storable (ParameterPacked a) where
-   sizeOf    = Store.sizeOf storeParameter
-   alignment = Store.alignment storeParameter
-   peek      = Store.peek storeParameter
-   poke      = Store.poke storeParameter
--}
-
-instance Storable a => Storable (ParameterPacked a) where
-   sizeOf    = Store.sizeOf
-   alignment = Store.alignment
-   peek      = Store.peekApplicative
-   poke      = Store.poke
-
-
-type ParameterPackedStruct a = LLVM.Struct (a, (a, ()))
-
-memory ::
-   (Memory.C a) =>
-   Memory.Record r (ParameterPackedStruct (Memory.Struct a)) (ParameterPacked a)
-memory =
-   liftA2 ParameterPacked
-      (Memory.element ppFeedback TypeNum.d0)
-      (Memory.element ppCurrent  TypeNum.d1)
-
-instance (Memory.C a) => Memory.C (ParameterPacked a) where
-   type Struct (ParameterPacked a) = ParameterPackedStruct (Memory.Struct a)
-   load = Memory.loadRecord memory
-   store = Memory.storeRecord memory
-   decompose = Memory.decomposeRecord memory
-   compose = Memory.composeRecord memory
-
-instance (Storable.C a) => Storable.C (ParameterPacked a) where
-   load = Storable.loadApplicative
-   store = Storable.storeFoldable
-
-
-{-
-instance LLVM.ValueTuple a => LLVM.ValueTuple (ParameterPacked a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
-
-instance LLVM.IsTuple a => LLVM.IsTuple (ParameterPacked a) where
-   tupleDesc = Class.tupleDescFoldable
--}
-
-instance (Tuple.Value a) => Tuple.Value (ParameterPacked a) where
-   type ValueOf (ParameterPacked a) = ParameterPacked (Tuple.ValueOf a)
-   valueOf = Tuple.valueOfFunctor
-
-
-instance (Value.Flatten a) => Value.Flatten (ParameterPacked a) where
-   type Registers (ParameterPacked a) = ParameterPacked (Value.Registers a)
-   flattenCode = Value.flattenCodeTraversable
-   unfoldCode = Value.unfoldCodeTraversable
-
-type instance F.Arguments f (ParameterPacked a) = f (ParameterPacked a)
-instance F.MakeArguments (ParameterPacked a) where
-   makeArgs = id
-
-
-
-withSize ::
-   (TypeNum.Natural n) =>
-   (Serial.C v, Serial.Size v ~ n, TypeNum.Positive n) =>
-   (TypeNum.Singleton n -> m (param v)) ->
-   m (param v)
-withSize f = f TypeNum.singleton
-
-parameterPacked ::
-   (Serial.C v, Serial.Element v ~ a,
-    A.PseudoRing v, A.RationalConstant v,
-    A.Transcendental a, A.RationalConstant a) =>
-   a -> CodeGenFunction r (ParameterPacked v)
-parameterPacked halfLife = withSize $ \n -> do
-   feedback <-
-      Serial.upsample =<<
-      A.pow (A.fromRational' 0.5) =<<
-      A.fdiv (A.fromInteger' $ TypeNum.integralFromSingleton n) halfLife
-   k <-
-      A.pow (A.fromRational' 0.5) =<<
-      A.fdiv (A.fromInteger' 1) halfLife
-   current <-
-      Serial.iterate (A.mul k) (A.fromInteger' 1)
-   return $ ParameterPacked feedback current
-{-
-   Value.unlift1 parameterPackedPlain
--}
-
-withSizePlain ::
-   (TypeNum.Natural n) =>
-   (TypeNum.Singleton n -> param (Serial.Plain n a)) ->
-   param (Serial.Plain n a)
-withSizePlain f = f TypeNum.singleton
-
-parameterPackedPlain ::
-   (Trans.C a,
-    TypeNum.Positive n) =>
-   a -> ParameterPacked (Serial.Plain n a)
-parameterPackedPlain halfLife =
-   withSizePlain $ \n ->
-   ParameterPacked
-      (Serial.replicate_ n (0.5 ** (fromInteger (TypeNum.integerFromSingleton n) / halfLife)))
-      (Serial.iteratePlain (0.5 ** recip halfLife *) one)
-
-
-withSizeValue ::
-   (TypeNum.Natural n) =>
-   (TypeNum.Singleton n -> f (Serial.Value n a)) ->
-   f (Serial.Value n a)
-withSizeValue f = f TypeNum.singleton
-
-causalPackedP ::
-   (IsArithmetic a, SoV.IntegerConstant a,
-    Marshal.C a, Tuple.ValueOf a ~ Value a,
-    Marshal.Vector n a, Tuple.VectorValueOf n a ~ Value (LLVM.Vector n a),
-    IsPrimitive a,
-    TypeNum.Positive (n :*: SizeOf a),
-    TypeNum.Positive n) =>
-   Param.T p a ->
-   CausalP.T p (ParameterPacked (Serial.Value n a)) (Serial.Value n a)
-causalPackedP initial =
-   withSizeValue $ \n ->
-   CausalP.loop
-      (Serial.replicate_ n ^<< initial)
-      (CausalP.mapSimple $
-       \(p, s0) -> liftM2 (,)
-          (A.mul (ppCurrent p) s0)
-          (A.mul (ppFeedback p) s0))
diff --git a/src/Synthesizer/LLVM/Generator/Extra.hs b/src/Synthesizer/LLVM/Generator/Extra.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Generator/Extra.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Generator.Extra where
+
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import Synthesizer.Causal.Class (($*))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+
+import Data.Word (Word)
+
+import NumericPrelude.Numeric
+
+
+
+ramp,
+ parabolaFadeIn, parabolaFadeOut,
+ parabolaFadeInMap, parabolaFadeOutMap ::
+   (Marshal.C a, MultiValue.Field a, MultiValue.IntegerConstant a,
+    MultiValue.NativeFloating a ar) =>
+   Exp Word -> Sig.MV a
+
+ramp dur =
+   Causal.take dur $* Sig.rampInf (Expr.fromIntegral dur)
+
+parabolaFadeIn dur =
+   Causal.take dur $* Sig.parabolaFadeInInf (Expr.fromIntegral dur)
+
+parabolaFadeOut dur =
+   Causal.take dur $* Sig.parabolaFadeOutInf (Expr.fromIntegral dur)
+
+parabolaFadeInMap dur = Causal.map (\t -> t*(2-t)) $* ramp dur
+parabolaFadeOutMap dur = Causal.map (\t -> 1-t*t) $* ramp dur
diff --git a/src/Synthesizer/LLVM/Generator/Private.hs b/src/Synthesizer/LLVM/Generator/Private.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Generator/Private.hs
@@ -0,0 +1,201 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Generator.Private where
+
+import Synthesizer.LLVM.Private (getPairPtrs, noLocalPtr)
+
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+import LLVM.Core (CodeGenFunction)
+
+import Type.Base.Proxy (Proxy(Proxy))
+
+import Control.Applicative (Applicative, liftA2, pure, (<*>), (<$>))
+
+import Data.Semigroup (Semigroup, (<>))
+import Data.Tuple.Strict (mapFst, zipPair)
+
+import qualified Number.Ratio as Ratio
+import qualified Algebra.Field as Field
+import qualified Algebra.Ring as Ring
+import qualified Algebra.Additive as Additive
+
+import qualified Prelude as P
+import Prelude hiding (iterate, takeWhile, map, zipWith)
+
+
+data T a =
+   forall global local state.
+      (Memory.C global, LLVM.IsSized local, Memory.C state) =>
+      Cons (forall r c.
+            (Tuple.Phi c) =>
+            global ->
+            -- pointer to loop local storage
+            LLVM.Value (LLVM.Ptr local) ->
+            state -> MaybeCont.T r c (a, state))
+               -- compute next value
+           (forall r. CodeGenFunction r (global, state))
+               -- initial state
+           (forall r. global -> CodeGenFunction r ())
+               -- cleanup
+
+
+noGlobal ::
+   (LLVM.IsSized local, Memory.C state) =>
+   (forall r c.
+    (Tuple.Phi c) =>
+    LLVM.Value (LLVM.Ptr local) -> state -> MaybeCont.T r c (a, state)) ->
+   (forall r. CodeGenFunction r state) ->
+   T a
+noGlobal next start = Cons (const next) (fmap ((,) ()) start) return
+
+alloca :: (LLVM.IsSized a) => T (LLVM.Value (LLVM.Ptr a))
+alloca =
+   noGlobal
+      (\ptr () -> return (ptr, ()))
+      (return ())
+
+
+iterate ::
+   (Memory.C a) =>
+   (forall r. a -> CodeGenFunction r a) ->
+   (forall r. CodeGenFunction r a) -> T a
+iterate f a =
+   noGlobal
+      (noLocalPtr $ \s -> fmap ((,) s) $ MaybeCont.lift $ f s)
+      a
+
+iterateParam ::
+   (Memory.C b, Memory.C a) =>
+   (forall r. b -> a -> CodeGenFunction r a) ->
+   (forall r. CodeGenFunction r b) ->
+   (forall r. CodeGenFunction r a) -> T a
+iterateParam f b a =
+   fmap snd $ iterate (\(bi,ai) -> (,) bi <$> f bi ai) (liftA2 (,) b a)
+
+takeWhile ::
+   (forall r. a -> CodeGenFunction r (LLVM.Value Bool)) -> T a -> T a
+takeWhile p (Cons next start stop) = Cons
+   (\global local s0 -> do
+      (a,s1) <- next global local s0
+      MaybeCont.guard =<< MaybeCont.lift (p a)
+      return (a,s1))
+   start
+   stop
+
+
+empty :: T a
+empty = noGlobal (noLocalPtr $ \ _state -> MaybeCont.nothing) (return ())
+
+{- |
+Appending many signals is inefficient,
+since in cascadingly appended signals the parts are counted in an unary way.
+Concatenating infinitely many signals is impossible.
+If you want to concatenate a lot of signals,
+please render them to lazy storable vectors first.
+-}
+{-
+We might save a little space by using a union
+for the states of the first and the second signal generator.
+If the concatenated generators allocate memory,
+we could also save some memory by calling @startB@
+only after the first generator finished.
+However, for correct deallocation
+we would need to track which of the @start@ blocks
+have been executed so far.
+This in turn might be difficult in connection with the garbage collector.
+-}
+append :: (Tuple.Phi a, Tuple.Undefined a) => T a -> T a -> T a
+append (Cons nextA startA stopA) (Cons nextB startB stopB) = Cons
+   (\(globalA, globalB) local (sa0,sb0,phaseB) -> do
+      (localA,localB) <- getPairPtrs local
+      MaybeCont.alternative
+         (do
+            MaybeCont.guard =<< MaybeCont.lift (LLVM.inv phaseB)
+            (a,sa1) <- nextA globalA localA sa0
+            return (a, (sa1, sb0, LLVM.valueOf False)))
+         (do
+            (b,sb1) <- nextB globalB localB sb0
+            return (b, (sa0, sb1, LLVM.valueOf True))))
+   (do
+      (globalA,stateA) <- startA
+      (globalB,stateB) <- startB
+      return ((globalA,globalB), (stateA, stateB, LLVM.valueOf False)))
+   (\(globalA,globalB) -> stopB globalB >> stopA globalA)
+
+instance (Tuple.Phi a, Tuple.Undefined a) => Semigroup (T a) where
+   (<>) = append
+
+instance (Tuple.Phi a, Tuple.Undefined a) => Monoid (T a) where
+   mempty = empty
+   mappend = (<>)
+
+
+
+instance Functor T where
+   fmap f (Cons next start stop) = Cons
+      (\global local s -> mapFst f <$> next global local s)
+      start stop
+
+instance Applicative T where
+   pure a = noGlobal (noLocalPtr $ \() -> return (a, ())) (return ())
+   Cons nextF startF stopF <*> Cons nextA startA stopA = Cons
+      (\(globalF, globalA) local (sf0,sa0) -> do
+         (localF,localA) <- getPairPtrs local
+         (f,sf1) <- nextF globalF localF sf0
+         (a,sa1) <- nextA globalA localA sa0
+         return (f a, (sf1,sa1)))
+      (liftA2 zipPair startF startA)
+      (\(globalF, globalA) -> stopA globalA >> stopF globalF)
+
+
+map :: (forall r. a -> CodeGenFunction r b) -> T a -> T b
+map f (Cons next start stop) =
+   Cons
+      (\global local sa0 -> do
+         (a,sa1) <- next global local sa0
+         b <- MaybeCont.lift $ f a
+         return (b, sa1))
+      start stop
+
+zipWith :: (forall r. a -> b -> CodeGenFunction r c) -> T a -> T b -> T c
+zipWith f as bs = map (uncurry f) $ liftA2 (,) as bs
+
+instance (A.Additive a) => Additive.C (T a) where
+   zero = pure A.zero
+   negate = map A.neg
+   (+) = zipWith A.add
+   (-) = zipWith A.sub
+
+instance (A.PseudoRing a, A.IntegerConstant a) => Ring.C (T a) where
+   one = pure A.one
+   fromInteger n = pure (A.fromInteger' n)
+   (*) = zipWith A.mul
+
+instance (A.Field a, A.RationalConstant a) => Field.C (T a) where
+   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
+   (/) = zipWith A.fdiv
+
+
+instance (A.PseudoRing a, A.Real a, A.IntegerConstant a) => P.Num (T a) where
+   fromInteger n = pure (A.fromInteger' n)
+   negate = map A.neg
+   (+) = zipWith A.add
+   (-) = zipWith A.sub
+   (*) = zipWith A.mul
+   abs = map A.abs
+   signum = map A.signum
+
+instance (A.Field a, A.Real a, A.RationalConstant a) => P.Fractional (T a) where
+   fromRational x = pure (A.fromRational' x)
+   (/) = zipWith A.fdiv
+
+
+
+arraySize :: value (array n a) -> Proxy n
+arraySize _ = Proxy
diff --git a/src/Synthesizer/LLVM/Generator/Render.hs b/src/Synthesizer/LLVM/Generator/Render.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Generator/Render.hs
@@ -0,0 +1,525 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+module Synthesizer.LLVM.Generator.Render where
+
+import qualified Synthesizer.LLVM.Causal.Parameterized as Parameterized
+import qualified Synthesizer.LLVM.Generator.Source as Source
+import qualified Synthesizer.LLVM.Storable.ChunkIterator as ChunkIt
+import qualified Synthesizer.LLVM.Storable.LazySizeIterator as SizeIt
+import qualified Synthesizer.LLVM.EventIterator as EventIt
+import Synthesizer.LLVM.Generator.Private (T(Cons))
+
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Storable.Vector as SVU
+import qualified Synthesizer.LLVM.ForeignPtr as ForeignPtr
+import qualified Synthesizer.LLVM.ConstantPiece as Const
+
+import qualified Synthesizer.PiecewiseConstant.Signal as PC
+import qualified Synthesizer.Causal.Class as CausalClass
+
+import qualified LLVM.DSL.Execution as Exec
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp(Exp))
+
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Maybe as Maybe
+import qualified LLVM.Extra.Control as C
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Data.StorableVector.Lazy as SVL
+import qualified Data.StorableVector.Base as SVB
+import qualified Data.StorableVector as SV
+
+import qualified Data.EventList.Relative.BodyTime as EventList
+import qualified Numeric.NonNegative.Wrapper as NonNeg
+import qualified Numeric.NonNegative.Chunky as NonNegChunky
+
+import Control.Monad (join)
+import Control.Applicative (liftA3)
+
+import Foreign.ForeignPtr (touchForeignPtr)
+import Foreign.Ptr (Ptr)
+
+import Data.Foldable (traverse_)
+import Data.Tuple.Strict (mapPair, mapTriple)
+import Data.Word (Word, Word8, Word32)
+
+import qualified System.Unsafe as Unsafe
+
+
+foreign import ccall safe "dynamic" derefFillPtr ::
+   Exec.Importer (LLVM.Ptr param -> Word -> Ptr struct -> IO Word)
+
+
+compile ::
+   (Storable.C a, MultiValue.T a ~ value,
+    Marshal.C param, Marshal.Struct param ~ paramStruct) =>
+   (Exp param -> T value) ->
+   IO (LLVM.Ptr paramStruct -> Word -> Ptr a -> IO Word)
+compile sig =
+   Exec.compile "signal" $
+   Exec.createFunction derefFillPtr "fill" $ \paramPtr size bPtr ->
+   case sig (Exp (Memory.load paramPtr)) of
+      Cons next start stop -> do
+         (global,s) <- start
+         local <- LLVM.alloca
+         (pos,_) <- Storable.arrayLoopMaybeCont size bPtr s $ \ ptri s0 -> do
+            (y,s1) <- next global local s0
+            MaybeCont.lift $ Storable.store y ptri
+            return s1
+         stop global
+         return pos
+
+runAux ::
+   (Marshal.C p, Storable.C a, MultiValue.T a ~ value) =>
+   (Exp p -> T value) -> IO (IO () -> Int -> p -> IO (SV.Vector a))
+runAux sig = do
+   fill <- compile sig
+   return $ \final len param ->
+      Marshal.with param $ \paramPtr ->
+      SVB.createAndTrim len $ \ptr -> do
+         n <- fill paramPtr (fromIntegral len) ptr
+         final
+         return $ fromIntegral n
+
+run_ ::
+   (Marshal.C p, Storable.C a, MultiValue.T a ~ value) =>
+   (Exp p -> T value) -> IO (Int -> p -> IO (SV.Vector a))
+run_ = fmap ($ return ()) . runAux
+
+
+foreign import ccall safe "dynamic" derefStartPtr ::
+   Exec.Importer (LLVM.Ptr param -> IO (LLVM.Ptr globalState))
+
+foreign import ccall safe "dynamic" derefStopPtr ::
+   Exec.Importer (LLVM.Ptr globalState -> IO ())
+
+foreign import ccall safe "dynamic" derefChunkPtr ::
+   Exec.Importer (LLVM.Ptr globalState -> Word -> Ptr a -> IO Word)
+
+
+type MemoryPtr a = LLVM.Ptr (Memory.Struct a)
+
+type WithGlobalState param = LLVM.Struct (param, ())
+
+type Pair a b = LLVM.Struct (a,(b,()))
+type Triple a b c = LLVM.Struct (a,(b,(c,())))
+
+tripleStruct ::
+   (LLVM.IsSized a, LLVM.IsSized b, LLVM.IsSized c) =>
+   LLVM.Value a -> LLVM.Value b -> LLVM.Value c ->
+   LLVM.CodeGenFunction r (LLVM.Value (Triple a b c))
+tripleStruct a b c = do
+   s0 <- LLVM.insertvalue Tuple.undef a TypeNum.d0
+   s1 <- LLVM.insertvalue s0 b TypeNum.d1
+   LLVM.insertvalue s1 c TypeNum.d2
+
+{- |
+This is a pretty ugly hack, but its seems to be the least ugly one.
+We need to solve the following problem:
+We have a function of type @Exp param -> T value@.
+This means that all methods in @T value@ depend on @Exp param@.
+We need to choose one piece of LLVM code in @Exp param@
+that generates appropriate code for all methods in @T value@.
+If we access a function parameter via @Memory.load paramPtr@
+this means that all methods must end up in the same LLVM function
+in order to access this parameter.
+Thus I have to put all functionality in one LLVM function
+and then the three functions in 'compileChunky'
+jump into the handler function with a 'Word8' code
+specifying the actual sub-routine.
+We need to squeeze all possible inputs and outputs
+through one function interface.
+
+However, since the handler is marked as internal
+the optimizer inlines it in the three functions from 'compileChunky'
+and eliminates dead code.
+This way, we end up with the code that we would have written otherwise.
+
+The alternative would be to construct @T value@ multiple times.
+Due to existential quantification we cannot prove
+that the pointer types of different methods match,
+so we need to cast pointers.
+However, with the current approach we also have to do that.
+-}
+compileHandler ::
+   (Marshal.C param, Marshal.Struct param ~ paramStruct,
+    Storable.C a, MultiValue.T a ~ value) =>
+   (Exp param -> T value) ->
+   LLVM.CodeGenModule
+      (LLVM.Function
+         (Word8 -> LLVM.Ptr paramStruct -> Word -> Ptr a ->
+          IO (Pair (LLVM.Ptr (WithGlobalState paramStruct)) Word)))
+compileHandler sig =
+   LLVM.createNamedFunction LLVM.InternalLinkage "handlesignal" $
+   \phase paramPtr loopLen bufferPtr ->
+   case sig $ Exp (Memory.load paramPtr) of
+      Cons next start stop -> do
+         paramGlobalStatePtr <- LLVM.bitcast paramPtr
+
+         let create = do
+               newParamGlobalStatePtr <- LLVM.malloc
+               (global,state) <- start
+               flip LLVM.store newParamGlobalStatePtr =<<
+                  join
+                     (liftA3 tripleStruct
+                        (LLVM.load paramPtr)
+                        (Memory.compose global)
+                        (Memory.compose state))
+               newOpaqueParamGlobalStatePtr <-
+                  LLVM.bitcast
+                     (newParamGlobalStatePtr `asTypeOf` paramGlobalStatePtr)
+               LLVM.insertvalue Tuple.undef
+                  newOpaqueParamGlobalStatePtr TypeNum.d0
+
+         let delete = do
+               globalPtr <-
+                  LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+               stop =<< Memory.load globalPtr
+               LLVM.free paramGlobalStatePtr
+               return Tuple.undef
+
+         let fill = do
+               globalPtr <-
+                  LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+               statePtr <-
+                  LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d2, ())
+               global <- Memory.load globalPtr
+               sInit <- Memory.load statePtr
+               local <- LLVM.alloca
+               (pos,sExit) <-
+                  Storable.arrayLoopMaybeCont loopLen bufferPtr sInit $
+                     \ ptr s0 -> do
+                  (y,s1) <- next global local s0
+                  MaybeCont.lift $ Storable.store y ptr
+                  return s1
+               Memory.store (Maybe.fromJust sExit) statePtr
+               LLVM.insertvalue Tuple.undef pos TypeNum.d1
+
+         doCreate <- A.cmp LLVM.CmpEQ (LLVM.valueOf 0) phase
+         doDelete <- A.cmp LLVM.CmpEQ (LLVM.valueOf 1) phase
+         C.ret =<<
+            (C.ifThenElse doCreate create $
+             C.ifThenElse doDelete delete fill)
+
+compileChunky ::
+   (LLVM.IsSized paramStruct, LLVM.Value (LLVM.Ptr paramStruct) ~ pPtr,
+    Memory.C state, Memory.Struct state ~ stateStruct,
+    Memory.C global, Memory.Struct global ~ globalStruct,
+    Triple paramStruct globalStruct stateStruct ~ triple,
+    LLVM.IsSized local,
+    Storable.C a, MultiValue.T a ~ value) =>
+   (forall r z. (Tuple.Phi z) =>
+    pPtr -> global -> LLVM.Value (LLVM.Ptr local) ->
+    () -> state -> MaybeCont.T r z (value, state)) ->
+   (forall r. pPtr -> LLVM.CodeGenFunction r (global, state)) ->
+   (forall r. pPtr -> global -> LLVM.CodeGenFunction r ()) ->
+   IO (LLVM.Ptr paramStruct -> IO (LLVM.Ptr triple),
+       Exec.Finalizer triple,
+       LLVM.Ptr triple -> Word -> Ptr a -> IO Word)
+compileChunky next start stop =
+   Exec.compile "signal-chunky" $
+   liftA3 (,,)
+      (Exec.createFunction derefStartPtr "startsignal" $
+         \paramPtr -> do
+            paramGlobalStatePtr <- LLVM.malloc
+            (global,state) <- start paramPtr
+            flip LLVM.store paramGlobalStatePtr =<<
+               join
+                  (liftA3 tripleStruct
+                     (LLVM.load paramPtr)
+                     (Memory.compose global)
+                     (Memory.compose state))
+            return paramGlobalStatePtr)
+      (Exec.createFinalizer derefStopPtr "stopsignal" $
+         \paramGlobalStatePtr -> do
+            paramPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d0, ())
+            stop paramPtr =<<
+               Memory.load =<<
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+            LLVM.free paramGlobalStatePtr)
+      (Exec.createFunction derefChunkPtr "fillsignal" $
+         \paramGlobalStatePtr loopLen ptr -> do
+            paramPtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d0, ())
+            global <-
+               Memory.load =<<
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d1, ())
+            statePtr <-
+               LLVM.getElementPtr0 paramGlobalStatePtr (TypeNum.d2, ())
+            sInit <- Memory.load statePtr
+            local <- LLVM.alloca
+            (pos,sExit) <-
+               Storable.arrayLoopMaybeCont loopLen ptr sInit $
+                  \ ptri s0 -> do
+               (y,s1) <- next paramPtr global local () s0
+               MaybeCont.lift $ Storable.store y ptri
+               return s1
+            Memory.store (Maybe.fromJust sExit) statePtr
+            return pos)
+
+
+runChunkyAux ::
+   (Storable.C a, MultiValue.T a ~ value, Marshal.C p) =>
+   (Exp p -> T value) -> IO (IO () -> SVL.ChunkSize -> p -> IO (SVL.Vector a))
+runChunkyAux sig = do
+   paramd <-
+      Parameterized.fromProcessPtr "Signal.run" (CausalClass.fromSignal . sig)
+   case paramd of
+      Parameterized.Cons next start stop -> do
+         (startFunc,stopFunc,fill) <- compileChunky next start stop
+         return $ \final (SVL.ChunkSize size) p -> do
+            statePtr <- ForeignPtr.newParamMV stopFunc startFunc p
+
+            let go =
+                  Unsafe.interleaveIO $ do
+                     v <-
+                        ForeignPtr.with statePtr $ \sptr ->
+                        SVB.createAndTrim size $
+                        fmap (fromIntegral :: Word -> Int) .
+                        fill sptr (fromIntegral size)
+                     (if SV.length v > 0
+                        then fmap (v:)
+                        else id) $
+                        (if SV.length v < size
+                           then final >> return []
+                           else go)
+            fmap SVL.fromChunks go
+
+runChunky ::
+   (Storable.C a, MultiValue.T a ~ value, Marshal.C p) =>
+   (Exp p -> T value) -> IO (SVL.ChunkSize -> p -> IO (SVL.Vector a))
+runChunky = fmap ($ return ()) . runChunkyAux
+
+
+runChunkyOnVector ::
+   (Storable.C a, MultiValue.T a ~ al) =>
+   (Storable.C b, MultiValue.T b ~ bl) =>
+   (T al -> T bl) ->
+   IO (SVL.ChunkSize -> SV.Vector a -> IO (SVL.Vector b))
+runChunkyOnVector sig = do
+   f <- runChunkyAux (sig . Source.storableVector)
+   return $ \chunkSize av -> do
+      let (fp,ptr,l) = SVU.unsafeToPointers av
+      f (touchForeignPtr fp) chunkSize (Source.consStorableVector ptr l)
+
+
+class Run f where
+   type DSL f
+   type Shape f
+   build ::
+      (Marshal.C p) =>
+      (Exp p -> DSL f) -> IO (IO (p, IO ()) -> Shape f -> f)
+
+instance (Storable.C a) => Run (SVL.Vector a) where
+   type DSL (SVL.Vector a) = T (MultiValue.T a)
+   type Shape (SVL.Vector a) = SVL.ChunkSize
+   build =
+      fmap (\f create shape -> Unsafe.performIO $ buildIOGen f create shape) .
+      runChunkyAux
+
+instance (Storable.C a) => Run (SV.Vector a) where
+   type DSL (SV.Vector a) = T (MultiValue.T a)
+   type Shape (SV.Vector a) = Int
+   build =
+      fmap (\f create shape -> Unsafe.performIO $ buildIOGen f create shape) .
+      runAux
+
+instance (RunIO a) => Run (IO a) where
+   type DSL (IO a) = T (DSL_IO a)
+   type Shape (IO a) = ShapeIO a
+   build = buildIO
+
+instance (RunArg a, Run f) => Run (a -> f) where
+   type DSL (a -> f) = DSLArg a -> DSL f
+   type Shape (a -> f) = Shape f
+   build sig =
+      case buildArg of
+         BuildArg pass createA -> do
+            f <- build (Expr.uncurry $ \p -> sig p . pass)
+            return $ \createP shape av ->
+               f (do (p,finalP) <- createP
+                     (pa,finalA) <- createA av
+                     return ((p,pa), finalA >> finalP))
+                  shape
+
+
+class RunIO a where
+   type DSL_IO a
+   type ShapeIO a
+   buildIO ::
+      (Marshal.C p) =>
+      (Exp p -> T (DSL_IO a)) -> IO (IO (p, IO ()) -> ShapeIO a -> IO a)
+
+instance (Storable.C a) => RunIO (SVL.Vector a) where
+   type DSL_IO (SVL.Vector a) = MultiValue.T a
+   type ShapeIO (SVL.Vector a) = SVL.ChunkSize
+   buildIO = fmap buildIOGen . runChunkyAux
+
+instance (Storable.C a) => RunIO (SV.Vector a) where
+   type DSL_IO (SV.Vector a) = MultiValue.T a
+   type ShapeIO (SV.Vector a) = Int
+   buildIO = fmap buildIOGen . runAux
+
+buildIOGen ::
+   (Monad m) => (final -> shape -> p -> m a) -> m (p, final) -> shape -> m a
+buildIOGen f create shape = do (p,final) <- create; f final shape p
+
+
+data BuildArg a =
+   forall al. Marshal.C al =>
+   BuildArg (Exp al -> DSLArg a) (a -> IO (al, IO ()))
+
+class RunArg a where
+   type DSLArg a
+   buildArg :: BuildArg a
+
+instance RunArg () where
+   type DSLArg () = ()
+   buildArg = BuildArg (\ _unit -> ()) (\() -> return ((), return ()))
+
+instance (RunArg a, RunArg b) => RunArg (a,b) where
+   type DSLArg (a,b) = (DSLArg a, DSLArg b)
+   buildArg =
+      case (buildArg,buildArg) of
+         (BuildArg passA createA, BuildArg passB createB) ->
+            BuildArg
+               (mapPair (passA,passB) . Expr.unzip)
+               (\(a,b) -> do
+                  (pa,finalA) <- createA a
+                  (pb,finalB) <- createB b
+                  return ((pa,pb), finalB>>finalA))
+
+instance (RunArg a, RunArg b, RunArg c) => RunArg (a,b,c) where
+   type DSLArg (a,b,c) = (DSLArg a, DSLArg b, DSLArg c)
+   buildArg =
+      case (buildArg,buildArg,buildArg) of
+         (BuildArg passA createA, BuildArg passB createB,
+          BuildArg passC createC) ->
+            BuildArg
+               (mapTriple (passA,passB,passC) . Expr.unzip3)
+               (\(a,b,c) -> do
+                  (pa,finalA) <- createA a
+                  (pb,finalB) <- createB b
+                  (pc,finalC) <- createC c
+                  return ((pa,pb,pc), finalC>>finalB>>finalA))
+
+primitiveArg :: (Marshal.C a, DSLArg a ~ Exp a) => BuildArg a
+primitiveArg = BuildArg id (\a -> return (a, return ()))
+
+instance RunArg Float where
+   type DSLArg Float = Exp Float
+   buildArg = primitiveArg
+
+instance RunArg Int where
+   type DSLArg Int = Exp Int
+   buildArg = primitiveArg
+
+instance RunArg Word where
+   type DSLArg Word = Exp Word
+   buildArg = primitiveArg
+
+instance RunArg Word32 where
+   type DSLArg Word32 = Exp Word32
+   buildArg = primitiveArg
+
+instance (RunArg a) => RunArg (Stereo.T a) where
+   type DSLArg (Stereo.T a) = Stereo.T (DSLArg a)
+   buildArg =
+      case buildArg of
+         BuildArg pass create ->
+            BuildArg
+               (fmap pass . Stereo.unExpression)
+               (\s -> do
+                  pf <- traverse create s
+                  return (fst<$>pf, traverse_ snd pf))
+
+instance
+   (TypeNum.Natural n, Marshal.C a, LLVM.IsSized (Marshal.Struct a),
+    TypeNum.Natural (n TypeNum.:*: LLVM.SizeOf (Marshal.Struct a))) =>
+      RunArg (MultiValue.Array n a) where
+   type DSLArg (MultiValue.Array n a) = Exp (MultiValue.Array n a)
+   buildArg = primitiveArg
+
+instance (Storable.C a) => RunArg (SV.Vector a) where
+   type DSLArg (SV.Vector a) = T (MultiValue.T a)
+   buildArg =
+      BuildArg
+         Source.storableVector
+         (\av -> do
+            let (fp,ptr,l) = SVU.unsafeToPointers av
+            return (Source.consStorableVector ptr l, touchForeignPtr fp))
+
+newtype Buffer a = Buffer (SV.Vector a)
+
+buffer :: SV.Vector a -> Buffer a
+buffer = Buffer
+
+instance (Storable.C a) => RunArg (Buffer a) where
+   type DSLArg (Buffer a) = Exp (Source.StorableVector a)
+   buildArg =
+      BuildArg id
+         (\(Buffer av) -> do
+            let (fp,ptr,l) = SVU.unsafeToPointers av
+            return (Source.consStorableVector ptr l, touchForeignPtr fp))
+
+newDisposeArg ::
+   (Marshal.C handle) =>
+   (a -> IO handle) -> (handle -> IO ()) ->
+   (Exp handle -> DSLArg a) -> BuildArg a
+newDisposeArg new dispose fetch =
+   BuildArg fetch
+      (\x -> do
+         it <- new x
+         return (it, dispose it))
+
+instance (Storable.C a) => RunArg (SVL.Vector a) where
+   type DSLArg (SVL.Vector a) = T (MultiValue.T a)
+   buildArg =
+      newDisposeArg ChunkIt.new ChunkIt.dispose Source.storableVectorLazy
+
+class TimeInteger int where
+   subdivideLong :: EventList.T (NonNeg.T int) a -> EventList.T NonNeg.Int a
+
+instance TimeInteger Int where
+   subdivideLong = id
+
+instance TimeInteger Integer where
+   subdivideLong = PC.subdivideLongStrict
+
+instance
+   (time ~ NonNeg.T int, TimeInteger int, Marshal.C a) =>
+      RunArg (EventList.T time a) where
+   type DSLArg (EventList.T time a) = T (Const.T (MultiValue.T a))
+   buildArg =
+      newDisposeArg
+         (EventIt.new . subdivideLong) EventIt.dispose Source.eventList
+
+instance (a ~ SVL.ChunkSize) => RunArg (NonNegChunky.T a) where
+   type DSLArg (NonNegChunky.T a) = T (Const.T ())
+   buildArg =
+      newDisposeArg SizeIt.new SizeIt.dispose Source.lazySize
+
+{-
+do f <- run (\n -> takeWhile (<*n) (iterate (1+) 0) <> takeWhile (<*n) (iterate (2+) 0)); f SVL.defaultChunkSize (12::Float) :: IO (SVL.Vector Float)
+do f <- Sig.run (\n -> Sig.takeWhile (Expr.<*n) (Sig.iterate (1+) 0) <> Sig.takeWhile (Expr.<*n) (Sig.iterate (2+) 0)); f SVL.defaultChunkSize (12::Float) :: IO (SVL.Vector Float)
+-}
+run :: (Run f) => DSL f -> IO (Shape f -> f)
+run sig = do
+   act <- build (const sig)
+   return $ act (return ((), return ()))
diff --git a/src/Synthesizer/LLVM/Generator/Signal.hs b/src/Synthesizer/LLVM/Generator/Signal.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Generator/Signal.hs
@@ -0,0 +1,345 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+module Synthesizer.LLVM.Generator.Signal (
+   Sig.T,
+   MV,
+
+   constant,
+   fromArray,
+   Core.iterate,
+   takeWhile,
+   take,
+   tail,
+   drop,
+   Sig.append,
+   cycle,
+
+   amplify,
+
+   osci,
+   exponential2,
+   exponentialBounded2,
+   noise,
+
+   adjacentNodes02,
+   adjacentNodes13,
+   interpolateConstant,
+
+   rampSlope,
+   rampInf,
+   ramp,
+   parabolaFadeInInf,
+   parabolaFadeOutInf,
+   parabolaFadeIn,
+   parabolaFadeOut,
+   parabolaFadeInMap,
+   parabolaFadeOutMap,
+   ) where
+
+import qualified Synthesizer.LLVM.Causal.Private as Causal
+import qualified Synthesizer.LLVM.Generator.Core as Core
+import qualified Synthesizer.LLVM.Generator.Private as Sig
+import qualified Synthesizer.LLVM.Interpolation as Interpolation
+import qualified Synthesizer.LLVM.Frame as Frame
+import qualified Synthesizer.LLVM.Random as Rnd
+import Synthesizer.LLVM.Generator.Private (arraySize)
+import Synthesizer.LLVM.Private (noLocalPtr)
+
+import qualified Synthesizer.Causal.Class as CausalC
+import Synthesizer.Causal.Class (apply, ($*), ($<))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Iterator as Iter
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.Core as LLVM
+import LLVM.Core (CodeGenFunction)
+
+import qualified Type.Data.Num.Decimal.Number as TypeNum
+import Type.Data.Num.Decimal.Number ((:*:))
+
+import Control.Monad.HT ((<=<))
+import Control.Applicative (liftA2)
+
+import Data.Word (Word32, Word)
+import Data.Int (Int32)
+
+import NumericPrelude.Numeric
+import NumericPrelude.Base hiding
+         (map, iterate, takeWhile, take, tail, drop, cycle)
+
+
+
+type MV a = Sig.T (MultiValue.T a)
+
+constant :: (Expr.Aggregate ae al, Memory.C al) => ae -> Sig.T al
+constant a = Sig.iterate return (Expr.bundle a)
+
+
+fromArray ::
+   (TypeNum.Natural n, Marshal.C a) =>
+   ((n :*: LLVM.SizeOf (Marshal.Struct a)) ~ arrSize,
+    TypeNum.Natural arrSize) =>
+   Exp (MultiValue.Array n a) -> MV a
+fromArray arrExp = Sig.Cons
+   (\arrPtr -> noLocalPtr $ \i -> do
+      inRange <- MaybeCont.lift $
+         LLVM.cmp LLVM.CmpLT i $ LLVM.valueOf $
+            TypeNum.integralFromProxy $ arraySize arrExp
+      MaybeCont.guard inRange
+      MaybeCont.lift $ do
+         ptr <- LLVM.getElementPtr0 arrPtr (i, ())
+         liftA2 (,) (Memory.load ptr) (A.inc i))
+   (do
+      arrPtr <- LLVM.malloc
+      flip Memory.store arrPtr =<< Expr.unExp arrExp
+      return (arrPtr, A.zero :: LLVM.Value Word))
+   LLVM.free
+
+
+takeWhile :: (Expr.Aggregate ae a) => (ae -> Exp Bool) -> Sig.T a -> Sig.T a
+takeWhile p =
+   Sig.takeWhile (fmap (\(MultiValue.Cons cont) -> cont) . Expr.unliftM1 p)
+
+take :: Exp Word -> Sig.T a -> Sig.T a
+take len =
+   liftA2 (flip const) $ takeWhile (0 Expr.<*) (Core.iterate (subtract 1) len)
+
+{- |
+@tail empty@ generates the empty signal.
+-}
+tail :: Sig.T a -> Sig.T a
+tail (Sig.Cons next start stop) = Sig.Cons
+   next
+   (do
+      local <- LLVM.alloca
+      (global,s0) <- start
+      MaybeCont.resolve (next global local s0)
+         (return (global,s0))
+         (\(_a,s1) -> return (global,s1)))
+   stop
+
+drop :: Exp Word -> Sig.T a -> Sig.T a
+drop n (Sig.Cons next start stop) = Sig.Cons
+   next
+   (do
+      local <- LLVM.alloca
+      (global,state0) <- start
+      ~(MultiValue.Cons nv) <- Expr.unExp n
+      state1 <-
+         Iter.mapWhileState_
+            (\_ s0 ->
+               MaybeCont.resolve (next global local s0)
+                  (return (LLVM.valueOf False, s0))
+                  (\(_a,s1) -> return (LLVM.valueOf True, s1)))
+            (Iter.countDown nv) state0
+      return (global,state1))
+   stop
+
+
+{- |
+> cycle empty == empty
+-}
+cycle :: (Tuple.Phi a, Tuple.Undefined a) => Sig.T a -> Sig.T a
+cycle (Sig.Cons next start stop) =
+   Sig.Cons
+      (\globalPtr local s0 ->
+         MaybeCont.alternative
+            (do
+               c0 <- MaybeCont.lift $ Memory.load globalPtr
+               next c0 local s0)
+            (do
+               (c1,s1) <- MaybeCont.lift $ do
+                  stop =<< Memory.load globalPtr
+                  cs1 <- start
+                  Memory.store (fst cs1) globalPtr
+                  return cs1
+               next c1 local s1))
+      (do
+         globalPtr <- LLVM.malloc
+         (global,state) <- start
+         Memory.store global globalPtr
+         return (globalPtr, state))
+      (\globalPtr -> do
+         stop =<< Memory.load globalPtr
+         LLVM.free globalPtr)
+
+
+amplify ::
+   (Expr.Aggregate ea a, Memory.C a, A.PseudoRing a) =>
+   ea -> Sig.T a -> Sig.T a
+amplify x = apply (Causal.zipWith Frame.amplifyMono $< constant x)
+
+
+rampInf, rampSlope,
+ parabolaFadeInInf, parabolaFadeOutInf ::
+   (Marshal.C a, MultiValue.Field a, MultiValue.IntegerConstant a) =>
+   Exp a -> MV a
+rampSlope slope  =  Core.ramp slope Expr.zero
+rampInf dur  =  rampSlope (Expr.recip dur)
+
+{-
+t*(2-t) = 1 - (t-1)^2
+
+(t+d)*(2-t-d) - t*(2-t)
+   = d*(2-t) - d*t - d^2
+   = 2*d*(1-t) - d^2
+   = d*(2*(1-t) - d)
+
+2*d*(1-t-d) + d^2  -  (2*d*(1-t) + d^2)
+   = -2*d^2
+-}
+parabolaFadeInInf dur =
+   Core.parabola
+      ((\d -> -2*d*d)  $ Expr.recip dur)
+      ((\d -> d*(2-d)) $ Expr.recip dur)
+      Expr.zero
+
+{-
+1-t^2
+-}
+parabolaFadeOutInf dur =
+   Core.parabola
+      ((\d -> -2*d*d) $ Expr.recip dur)
+      ((\d ->   -d*d) $ Expr.recip dur)
+      Expr.one
+
+ramp,
+ parabolaFadeIn, parabolaFadeOut,
+ parabolaFadeInMap, parabolaFadeOutMap ::
+   (Marshal.C a, MultiValue.Field a, MultiValue.IntegerConstant a,
+    MultiValue.NativeFloating a ar) =>
+   Exp Word -> MV a
+
+ramp dur =
+   take dur $ rampInf (Expr.fromIntegral dur)
+
+parabolaFadeIn dur =
+   take dur $ parabolaFadeInInf (Expr.fromIntegral dur)
+
+parabolaFadeOut dur =
+   take dur $ parabolaFadeOutInf (Expr.fromIntegral dur)
+
+parabolaFadeInMap dur =
+   Causal.map (Expr.unliftM1 (\t -> t*(2-t))) $* ramp dur
+
+parabolaFadeOutMap dur =
+   Causal.map (Expr.unliftM1 (\t -> 1-t*t)) $* ramp dur
+
+
+osci ::
+   (MultiValue.Fraction t, Marshal.C t) =>
+   (forall r. MultiValue.T t -> CodeGenFunction r y) ->
+   Exp t -> Exp t -> Sig.T y
+osci wave phase freq  =  Causal.map wave $* Core.osci phase freq
+
+
+exponential2 ::
+   (Marshal.C a) =>
+   (MultiValue.Real a) =>
+   (MultiValue.RationalConstant a) =>
+   (MultiValue.Transcendental a) =>
+   Exp a -> Exp a -> MV a
+exponential2 halfLife  =  Core.exponential (1 / 2 ** recip halfLife)
+
+exponentialBounded2 ::
+   (Marshal.C a) =>
+   (MultiValue.Real a) =>
+   (MultiValue.RationalConstant a) =>
+   (MultiValue.Transcendental a) =>
+   Exp a -> Exp a -> Exp a -> MV a
+exponentialBounded2 bound halfLife =
+   Core.exponentialBounded bound (1 / 2 ** recip halfLife)
+
+
+{- |
+@noise seed rate@
+
+The @rate@ parameter is for adjusting the amplitude
+such that it is uniform across different sample rates
+and after frequency filters.
+The @rate@ is the ratio of the current sample rate to the default sample rate,
+where the variance of the samples would be one.
+If you want that at sample rate 22050 the variance is 1,
+then in order to get a consistent volume at sample rate 44100
+you have to set @rate = 2@.
+
+I use the variance as quantity and not the amplitude,
+because the amplitude makes only sense for uniformly distributed samples.
+However, frequency filters transform the probabilistic density of the samples
+towards the normal distribution according to the central limit theorem.
+-}
+noise ::
+   (Marshal.C a, MultiValue.Transcendental a, MultiValue.RationalConstant a,
+    MultiValue.NativeFloating a ar) =>
+   Exp Word32 -> Exp a -> MV a
+noise seed rate =
+   let m2 = Expr.fromInteger' $ div Rnd.modulus 2
+       r = sqrt (3 * rate) / m2
+   in  Causal.map (Expr.unliftM1 (\y -> r * (int31tofp y - (m2+1)))) $*
+       Core.noise seed
+
+{-
+sitofp is a single instruction on x86
+and thus we use it, since the arguments are below 2^31.
+-}
+int31tofp ::
+   (MultiValue.NativeFloating a ar) =>
+   Exp Word32 -> Exp a
+int31tofp =
+   Expr.liftM
+      (MultiValue.fromIntegral <=<
+       (MultiValue.liftM LLVM.bitcast ::
+         MultiValue.T Word32 -> CodeGenFunction r (MultiValue.T Int32)))
+
+
+adjacentNodes02 ::
+   (Memory.C a) =>
+   Sig.T a -> Sig.T (Interpolation.Nodes02 a)
+adjacentNodes02 =
+   tail
+   .
+   apply
+      (Causal.mapAccum
+         (\new old -> return (Interpolation.Nodes02 old new, new))
+         (return Tuple.undef))
+
+adjacentNodes13 ::
+   (Marshal.C a, MultiValue.T a ~ al) =>
+   Exp a -> Sig.T al -> Sig.T (Interpolation.Nodes13 al)
+adjacentNodes13 yp0 =
+   tail .
+   tail .
+   apply
+      (Causal.mapAccum
+         (\new (x0, x1, x2) ->
+            return (Interpolation.Nodes13 x0 x1 x2 new, (x1, x2, new)))
+         (do
+            y0 <- Expr.unExp yp0
+            return (MultiValue.undef, MultiValue.undef, y0)))
+
+
+{- |
+Stretch signal in time by a certain factor.
+
+This can be used for doing expensive computations
+of filter parameters at a lower rate.
+Alternatively, we could provide an adaptive @map@
+that recomputes output values only if the input value changes,
+or if the input value differs from the last processed one by a certain amount.
+-}
+interpolateConstant ::
+   (Memory.C a, Marshal.C b, MultiValue.IntegerConstant b,
+    MultiValue.Additive b, MultiValue.Comparison b) =>
+   Exp b -> Sig.T a -> Sig.T a
+interpolateConstant k sig =
+   CausalC.toSignal (Causal.quantizeLift (CausalC.fromSignal sig) $< constant k)
diff --git a/src/Synthesizer/LLVM/Generator/SignalPacked.hs b/src/Synthesizer/LLVM/Generator/SignalPacked.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Generator/SignalPacked.hs
@@ -0,0 +1,351 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE FlexibleContexts #-}
+{- |
+Signal generators that generate the signal in chunks
+that can be processed natively by the processor.
+Some of the functions for plain signals can be re-used without modification.
+E.g. rendering a signal and reading from and to signals work
+because the vector type as element type warrents correct alignment.
+We can convert between atomic and chunked signals.
+
+The article
+<http://perilsofparallel.blogspot.com/2008/09/larrabee-vs-nvidia-mimd-vs-simd.html>
+explains the difference between Vector and SIMD computing.
+According to that the SSE extensions in Intel processors
+must be called Vector computing.
+But since we use the term Vector already in the mathematical sense,
+I like to use the term "packed" that is used in Intel mnemonics like mulps.
+-}
+module Synthesizer.LLVM.Generator.SignalPacked (
+   pack, packRotate,
+   packSmall,
+   unpack, unpackRotate,
+   constant,
+   exponential2,
+   exponentialBounded2,
+   osciCore,
+   osci,
+   parabolaFadeInInf, parabolaFadeOutInf,
+   rampInf, rampSlope,
+   noise,
+   noiseCore, noiseCoreAlt,
+   ) where
+
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Private as Priv
+import qualified Synthesizer.LLVM.Generator.Core as Core
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as SerialClass
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as SerialCode
+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Random as Rnd
+
+import Synthesizer.Causal.Class (($*))
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Vector as MultiVector
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Vector as MultiValueVec
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.MaybeContinuation as Maybe
+import qualified LLVM.Extra.Control as U
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified Type.Data.Num.Decimal as TypeNum
+import Type.Data.Num.Decimal ((:*:))
+
+import qualified LLVM.Core as LLVM
+
+import qualified Control.Monad.Trans.Class as MT
+import qualified Control.Monad.Trans.State as MS
+import Control.Monad.HT ((<=<))
+import Control.Monad (replicateM)
+import Control.Applicative ((<$>))
+
+import qualified Algebra.Ring as Ring
+
+import Data.Tuple.HT (mapSnd)
+import Data.Word (Word32, Word)
+import Data.Int (Int32)
+
+import NumericPrelude.Numeric
+import NumericPrelude.Base
+
+
+
+{- |
+Convert a signal of scalar values into one using processor vectors.
+If the signal length is not divisible by the chunk size,
+then the last chunk is dropped.
+-}
+pack, packRotate ::
+   (SerialClass.Write v, a ~ SerialClass.Element v) =>
+   Sig.T a -> Sig.T v
+pack = packRotate
+
+packRotate (Priv.Cons next start stop) = Priv.Cons
+   (\global local s -> do
+      wInit <- Maybe.lift $ SerialClass.writeStart
+      (w2,_,s2) <-
+         Maybe.fromBool $
+         U.whileLoop
+            (LLVM.valueOf True,
+             (wInit,
+              LLVM.valueOf $ (SerialClass.sizeOfIterator wInit :: Word),
+              s))
+            (\(cont,(_w0,i0,_s0)) ->
+               A.and cont =<<
+                  A.cmp LLVM.CmpGT i0 A.zero)
+            (\(_,(w0,i0,s0)) -> Maybe.toBool $ do
+               (a,s1) <- next global local s0
+               Maybe.lift $ do
+                  w1 <- SerialClass.writeNext a w0
+                  i1 <- A.dec i0
+                  return (w1,i1,s1))
+      v <- Maybe.lift $ SerialClass.writeStop w2
+      return (v, s2))
+   start
+   stop
+
+{-
+We could reformulate it in terms of WriteIterator
+that accesses elements using LLVM.extract.
+We might move the loop counter into the Iterator,
+but we have to assert that the counter is not duplicated.
+
+packIndex ::
+   (SerialClass.Write v, a ~ SerialClass.Element v) =>
+   Sig.T a -> Sig.T v
+packIndex = alter (\(Core next start stop) -> Core
+   (\param s -> do
+      (v2,_,s2) <-
+         Maybe.fromBool $
+         U.whileLoop
+            (LLVM.valueOf True, (Tuple.undef, A.zero, s))
+            (\(cont,(v0,i0,_s0)) ->
+               A.and cont =<<
+                  A.cmp LLVM.CmpLT i0 (LLVM.valueOf $ SerialClass.size v0))
+            (\(_,(v0,i0,s0)) -> Maybe.toBool $ do
+               (a,s1) <- next param s0
+               Maybe.lift $ do
+                  v1 <- Vector.insert i0 a v0
+                  i1 <- A.inc i0
+                  return (v1,i1,s1))
+      return (v2, s2))
+   start
+   stop)
+-}
+
+
+{- |
+Like 'pack' but duplicates the code for creating elements.
+That is, for vectors of size n, the code of the input signal
+will be emitted n times.
+This is efficient only for simple input generators.
+-}
+packSmall ::
+   (SerialClass.Write v, a ~ SerialClass.Element v) =>
+   Sig.T a -> Sig.T v
+packSmall (Priv.Cons next start stop) = Priv.Cons
+   (\global local ->
+      MS.runStateT $
+      SerialClass.withSize $ \n ->
+         MT.lift . Maybe.lift . SerialClass.assemble
+         =<<
+         replicateM n (MS.StateT $ next global local))
+   start
+   stop
+
+
+unpack, unpackRotate ::
+   (SerialClass.Read v, a ~ SerialClass.Element v,
+    SerialClass.ReadIt v ~ itv, Memory.C itv) =>
+   Sig.T v -> Sig.T a
+unpack = unpackRotate
+
+unpackRotate (Priv.Cons next start stop) = Priv.Cons
+   (\global local (i0,r0,s0) -> do
+      endOfVector <-
+         Maybe.lift $ A.cmp LLVM.CmpEQ i0 (LLVM.valueOf (0::Word))
+      (i2,r2,s2) <-
+         Maybe.fromBool $
+         U.ifThen endOfVector (LLVM.valueOf True, (i0,r0,s0)) $ do
+            (cont1, (v1,s1)) <- Maybe.toBool $ next global local s0
+            r1 <- SerialClass.readStart v1
+            return (cont1, (LLVM.valueOf $ SerialClass.size v1, r1, s1))
+      Maybe.lift $ do
+         (a,r3) <- SerialClass.readNext r2
+         i3 <- A.dec i2
+         return (a, (i3,r3,s2)))
+   (mapSnd (\s -> (A.zero, Tuple.undef, s)) <$> start)
+   stop
+
+
+{-
+We could reformulate it in terms of ReadIterator
+that accesses elements using LLVM.extract.
+We might move the loop counter into the Iterator,
+but we have to assert that the counter is not duplicated.
+
+unpackIndex ::
+   (SerialClass.Write v, a ~ SerialClass.Element v, Memory.C v) =>
+   Sig.T v -> Sig.T a
+unpackIndex = alter (\(Core next start stop) -> Core
+   (\param (i0,v0,s0) -> do
+      endOfVector <-
+         Maybe.lift $ A.cmp LLVM.CmpGE i0 (LLVM.valueOf $ SerialClass.size v0)
+      (i2,v2,s2) <-
+         Maybe.fromBool $
+         U.ifThen endOfVector (LLVM.valueOf True, (i0,v0,s0)) $ do
+            (cont1, (v1,s1)) <- Maybe.toBool $ next param s0
+            return (cont1, (A.zero, v1, s1))
+      Maybe.lift $ do
+         a <- Vector.extract i2 v2
+         i3 <- A.inc i2
+         return (a, (i3,v2,s2)))
+   (\p -> do
+      s <- start p
+      let v = Tuple.undef
+      return (LLVM.valueOf $ SerialClass.size v, v, s))
+   stop)
+-}
+
+
+
+type Serial n a = SerialCode.Value n a
+
+withSize ::
+   (TypeNum.Positive n) =>
+   (TypeNum.Singleton n -> Sig.T (Serial n a)) ->
+   Sig.T (Serial n a)
+withSize f = f TypeNum.singleton
+
+withSizeRing ::
+   (Ring.C b, TypeNum.Positive n) =>
+   (b -> Sig.T (Serial n a)) ->
+   Sig.T (Serial n a)
+withSizeRing f =
+   withSize $ f . fromInteger . TypeNum.integerFromSingleton
+
+
+constant ::
+   (Marshal.Vector n a) =>
+   Exp a -> Sig.T (Serial n a)
+constant = Sig.constant . Serial.upsample
+
+
+exponential2 ::
+   (Marshal.Vector n a, MultiVector.Transcendental a,
+    MultiValue.RationalConstant a) =>
+   Exp a -> Exp a -> Sig.T (Serial n a)
+exponential2 halfLife start = withSizeRing $ \n ->
+   Core.exponential
+      (Serial.upsample (0.5 ** (n / halfLife)))
+      (Serial.iterate (0.5 ** recip halfLife *) start)
+
+exponentialBounded2 ::
+   (Marshal.Vector n a, MultiVector.Transcendental a,
+    MultiValue.RationalConstant a,
+    MultiVector.IntegerConstant a, MultiVector.Real a) =>
+   Exp a -> Exp a -> Exp a -> Sig.T (Serial n a)
+exponentialBounded2 bound halfLife start = withSizeRing $ \n ->
+   Core.exponentialBounded
+      (Serial.upsample bound)
+      (Serial.upsample (0.5 ** (n / halfLife)))
+      (Serial.iterate (0.5 ** recip halfLife *) start)
+
+osciCore ::
+   (Marshal.Vector n t, MultiVector.PseudoRing t, MultiVector.Fraction t,
+    MultiValue.IntegerConstant t) =>
+   Exp t -> Exp t -> Sig.T (Serial n t)
+osciCore phase freq = withSizeRing $ \n ->
+   Core.osci
+      (Serial.iterate (Expr.fraction . (freq +)) phase)
+      (Serial.upsample (Expr.fraction (n * freq)))
+
+osci ::
+   (Marshal.Vector n t, MultiVector.PseudoRing t, MultiVector.Fraction t,
+    MultiValue.IntegerConstant t) =>
+   (forall r. Serial n t -> LLVM.CodeGenFunction r y) ->
+   Exp t -> Exp t -> Sig.T y
+osci wave phase freq = Priv.map wave $ osciCore phase freq
+
+
+rampInf, rampSlope, parabolaFadeInInf, parabolaFadeOutInf ::
+   (Marshal.Vector n a, MultiVector.Field a, MultiVector.IntegerConstant a,
+    MultiValue.RationalConstant a) =>
+   Exp a -> Sig.T (Serial n a)
+rampSlope slope = withSizeRing $ \n ->
+   Core.ramp
+      (Serial.upsample (n * slope))
+      (Serial.iterate (slope +) 0)
+rampInf dur = rampSlope (Expr.recip dur)
+
+parabolaFadeInInf dur = withSizeRing $ \n ->
+   let d = n/dur
+   in Core.parabola
+         (Serial.upsample (-2*d*d))
+         (Serial.iterate (subtract $ 2 / dur ^ 2) (d*(2-d)))
+         ((\t -> t*(2-t)) $ Serial.iterate (recip dur +) 0)
+
+parabolaFadeOutInf dur = withSizeRing $ \n ->
+   let d = n/dur
+   in Core.parabola
+         (Serial.upsample (-2*d*d))
+         (Serial.iterate (subtract $ 2 / dur ^ 2) (-d*d))
+         ((\t -> 1-t*t) $ Serial.iterate (recip dur +) 0)
+
+
+{- |
+For the mysterious rate parameter see 'Sig.noise'.
+-}
+noise ::
+   (MultiVector.NativeFloating n a ar) =>
+   (MultiVector.PseudoRing a, MultiVector.IntegerConstant a) =>
+   (MultiValue.Algebraic a, MultiValue.RationalConstant a) =>
+   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
+   Exp Word32 -> Exp a -> Sig.T (Serial n a)
+noise seed rate =
+   let m2 = div Rnd.modulus 2
+       r = Serial.upsample $ Expr.sqrt (3*rate) / Expr.fromInteger' m2
+   in Causal.map
+         (\y -> r * (Expr.liftM int31tofp y - Expr.fromInteger' (m2+1))) $*
+      noiseCoreAlt seed
+
+{-
+sitofp is a single instruction on x86
+and thus we use it, since the arguments are below 2^31.
+
+It would be better to use LLVM's range annotation, instead.
+-}
+int31tofp ::
+   (MultiVector.NativeFloating n a ar,
+    TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
+   Serial n Word32 -> LLVM.CodeGenFunction r (Serial n a)
+int31tofp =
+   fmap SerialCode.fromOrdinary . MultiValueVec.fromIntegral .
+   SerialCode.toOrdinary . forceInt32
+      <=< MultiValue.liftM LLVM.bitcast
+
+type Id a = a -> a
+
+forceInt32 :: Id (Serial n Int32)
+forceInt32 = id
+
+noiseCore, noiseCoreAlt ::
+   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
+   Exp Word32 -> Sig.T (Serial n Word32)
+noiseCore    = Sig.iterate (Expr.liftReprM Rnd.nextVector)   . vectorSeed
+noiseCoreAlt = Sig.iterate (Expr.liftReprM Rnd.nextVector64) . vectorSeed
+
+vectorSeed :: (TypeNum.Positive n) => Exp Word32 -> Exp (Serial.T n Word32)
+vectorSeed seed =
+   Serial.iterate (Expr.liftReprM Rnd.nextCG) $
+   Expr.irem seed (fromInteger Rnd.modulus - 1) + 1
diff --git a/src/Synthesizer/LLVM/Generator/Source.hs b/src/Synthesizer/LLVM/Generator/Source.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Generator/Source.hs
@@ -0,0 +1,148 @@
+{-# LANGUAGE TypeFamilies #-}
+module Synthesizer.LLVM.Generator.Source where
+
+import qualified Synthesizer.LLVM.Storable.ChunkIterator as ChunkIt
+import qualified Synthesizer.LLVM.Storable.LazySizeIterator as SizeIt
+import qualified Synthesizer.LLVM.Generator.Private as Sig
+import qualified Synthesizer.LLVM.ConstantPiece as Const
+import qualified Synthesizer.LLVM.EventIterator as EventIt
+import Synthesizer.LLVM.Private (noLocalPtr)
+
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Extra.Control as C
+
+import qualified LLVM.Core as LLVM
+
+import Foreign.Storable (Storable)
+import Foreign.StablePtr (StablePtr)
+import Foreign.Ptr (Ptr, nullPtr)
+
+import Control.Applicative (liftA2, (<$>))
+
+import Data.Tuple.HT (mapSnd)
+import Data.Word (Word)
+
+
+type T a = Sig.T (MultiValue.T a)
+
+
+data StorableVector a = StorableVector (Ptr a) Word
+
+storableVectorLength :: Exp (StorableVector a) -> Exp Word
+storableVectorLength = Expr.lift1 (MultiValue.lift1 (\(_ptr,l) -> l))
+
+consStorableVector :: Ptr a -> Int -> StorableVector a
+consStorableVector p = StorableVector p . fromIntegral
+
+instance (Storable a) => MultiValue.C (StorableVector a) where
+   type Repr (StorableVector a) = (LLVM.Value (Ptr a), LLVM.Value Word)
+   cons (StorableVector p l) = MultiValue.Cons (LLVM.valueOf p, LLVM.valueOf l)
+   undef = MultiValue.undefTuple
+   zero = MultiValue.zeroTuple
+   phi = MultiValue.phiTuple
+   addPhi = MultiValue.addPhiTuple
+
+instance (Storable a) => Marshal.C (StorableVector a) where
+   pack (StorableVector p l) = LLVM.consStruct p l
+   unpack = LLVM.uncurryStruct StorableVector
+
+storableVector :: (Storable.C a) => Exp (StorableVector a) -> T a
+storableVector vec =
+   Sig.noGlobal
+      (noLocalPtr $ \(p0,l0) -> do
+         cont <- MaybeCont.lift $ A.cmp LLVM.CmpGT l0 A.zero
+         MaybeCont.withBool cont $ do
+            y1 <- Storable.load p0
+            p1 <- Storable.incrementPtr p0
+            l1 <- A.dec l0
+            return (y1,(p1,l1)))
+      (fmap (\(MultiValue.Cons (p,l)) -> (p,l)) (Expr.unExp vec))
+
+
+{-
+This function calls back into the Haskell function 'ChunkIt.next'
+that returns a pointer to the data of the next chunk
+and advances to the next chunk in the sequence.
+-}
+storableVectorLazy ::
+   (Storable.C a) => Exp (StablePtr (ChunkIt.T a)) -> T a
+storableVectorLazy = flattenChunks . storableVectorChunks
+
+type Chunk a = (LLVM.Value (Ptr a), LLVM.Value Word)
+
+storableVectorChunks ::
+   (Storable.C a) => Exp (StablePtr (ChunkIt.T a)) -> Sig.T (Chunk a)
+storableVectorChunks sig =
+   Sig.Cons
+      (\stable lenPtr () -> MaybeCont.fromBool $ do
+         nextChunkFn <-
+            LLVM.staticNamedFunction
+               "SignalExp.fromStorableVectorLazy.nextChunk"
+               ChunkIt.nextCallBack
+         (buffer,len) <-
+            liftA2 (,)
+               (LLVM.call nextChunkFn stable lenPtr)
+               (LLVM.load lenPtr)
+         valid <- A.cmp LLVM.CmpNE buffer (LLVM.valueOf nullPtr)
+         return (valid, ((buffer,len), ())))
+      (fmap (\(MultiValue.Cons it) -> (it, ())) $ Expr.unExp sig)
+      (\ _it -> return ())
+
+flattenChunks :: (Storable.C a) => Sig.T (Chunk a) -> T a
+flattenChunks (Sig.Cons next start stop) =
+   Sig.Cons
+      (\global local ((buffer0,length0), state0) -> do
+         ((buffer1,length1), state1) <- MaybeCont.fromBool $ do
+            needNext <- A.cmp LLVM.CmpEQ length0 A.zero
+            C.ifThen needNext
+               (LLVM.valueOf True, ((buffer0,length0), state0))
+               (MaybeCont.toBool $ next global local state0)
+         MaybeCont.lift $ do
+            x <- Storable.load buffer1
+            buffer2 <- Storable.incrementPtr buffer1
+            length2 <- A.dec length1
+            return (x, ((buffer2,length2), state1)))
+      (mapSnd ((,) (LLVM.valueOf nullPtr, A.zero)) <$> start)
+      stop
+
+
+eventList ::
+   (Marshal.C a) =>
+   Exp (StablePtr (EventIt.T a)) -> Sig.T (Const.T (MultiValue.T a))
+eventList sig =
+   Sig.Cons
+      -- FixMe: duplicate of ConstantPiece.piecewiseConstant
+      (\stable yPtr () -> do
+         len <- MaybeCont.lift $ do
+            nextFn <-
+               LLVM.staticNamedFunction
+                  "ConstantPiece.piecewiseConstant.nextChunk"
+                  EventIt.nextCallBack
+            LLVM.call nextFn stable yPtr
+         MaybeCont.guard =<< MaybeCont.lift (A.cmp LLVM.CmpNE len A.zero)
+         y <- MaybeCont.lift $ Memory.load yPtr
+         return (Const.Cons len y, ()))
+      (fmap (\(MultiValue.Cons it) -> (it, ())) $ Expr.unExp sig)
+      (\ _it -> return ())
+
+lazySize :: Exp (StablePtr SizeIt.T) -> Sig.T (Const.T ())
+lazySize size = Sig.Cons
+   (\stable -> noLocalPtr $ \() -> do
+      len <- MaybeCont.lift $ do
+         nextFn <-
+            LLVM.staticNamedFunction
+               "ConstantPiece.lazySize.next"
+               SizeIt.nextCallBack
+         LLVM.call nextFn stable
+      MaybeCont.guard =<< MaybeCont.lift (A.cmp LLVM.CmpNE len A.zero)
+      return (Const.Cons len (), ()))
+   (fmap (\(MultiValue.Cons it) -> (it, ())) $ Expr.unExp size)
+   (\ _it -> return ())
diff --git a/src/Synthesizer/LLVM/Interpolation.hs b/src/Synthesizer/LLVM/Interpolation.hs
--- a/src/Synthesizer/LLVM/Interpolation.hs
+++ b/src/Synthesizer/LLVM/Interpolation.hs
@@ -1,12 +1,19 @@
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module Synthesizer.LLVM.Interpolation (
    C(margin),
    loadNodes,
    indexNodes,
+   loadNodesExp,
+   indexNodesExp,
 
    Margin(..),
+   zipMargin,
+   unzipMargin,
    toMargin,
+   marginNumberExp,
+   marginOffsetExp,
 
    T,
 
@@ -19,11 +26,14 @@
    cubicVector,
    ) where
 
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Value as Value
 
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector.Class as Serial
 import qualified Synthesizer.Interpolation.Core as Interpolation
 
+import qualified LLVM.DSL.Expression as Expr
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Scalar as Scalar
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Tuple as Tuple
@@ -33,6 +43,7 @@
 
 import LLVM.Core (CodeGenFunction, Value)
 
+import Foreign.Storable (Storable)
 import Foreign.Ptr (Ptr)
 import Data.Word (Word)
 
@@ -44,13 +55,47 @@
 import Data.Foldable (Foldable, foldMap)
 
 
-class (Applicative nodes, Traversable nodes) => C nodes where
-   margin :: Margin (nodes a)
-
 data Margin nodes = Margin { marginNumber, marginOffset :: Int }
    deriving (Show, Eq)
 
+singletonMargin :: MultiValue.T Int -> MultiValue.T (Margin nodes)
+singletonMargin n = zipMargin n n
 
+unzipMargin ::
+   MultiValue.T (Margin nodes) -> (MultiValue.T Int, MultiValue.T Int)
+unzipMargin (MultiValue.Cons (from, to)) =
+   (MultiValue.Cons from, MultiValue.Cons to)
+
+zipMargin :: MultiValue.T Int -> MultiValue.T Int -> MultiValue.T (Margin nodes)
+zipMargin (MultiValue.Cons from) (MultiValue.Cons to) =
+   MultiValue.Cons (from, to)
+
+marginNumberExp :: (Expr.Value val) => val (Margin nodes) -> val Int
+marginNumberExp = Expr.lift1 (fst . unzipMargin)
+
+marginOffsetExp :: (Expr.Value val) => val (Margin nodes) -> val Int
+marginOffsetExp = Expr.lift1 (snd . unzipMargin)
+
+instance MultiValue.C (Margin nodes) where
+   type Repr (Margin nodes) = (LLVM.Value Int, LLVM.Value Int)
+   cons (Margin start len) =
+      zipMargin (MultiValue.cons start) (MultiValue.cons len)
+   undef = singletonMargin MultiValue.undef
+   zero = singletonMargin MultiValue.zero
+   phi bb a =
+      case unzipMargin a of
+         (a0,a1) ->
+            liftA2 zipMargin (MultiValue.phi bb a0) (MultiValue.phi bb a1)
+   addPhi bb a b =
+      case (unzipMargin a, unzipMargin b) of
+         ((a0,a1), (b0,b1)) -> do
+            MultiValue.addPhi bb a0 b0
+            MultiValue.addPhi bb a1 b1
+
+
+class (Applicative nodes, Traversable nodes) => C nodes where
+   margin :: Margin (nodes a)
+
 type T r nodes a v = a -> nodes v -> CodeGenFunction r v
 
 
@@ -96,7 +141,7 @@
    readStart = Serial.readStartTraversable
    readNext = Serial.readNextTraversable
 
-instance (Serial.C v) => Serial.C (Nodes02 v) where
+instance (Serial.Write v) => Serial.Write (Nodes02 v) where
    type WriteIt (Nodes02 v) = Nodes02 (Serial.WriteIt v)
 
    insert = Serial.insertTraversable
@@ -183,7 +228,7 @@
    readStart = Serial.readStartTraversable
    readNext = Serial.readNextTraversable
 
-instance (Serial.C v) => Serial.C (Nodes13 v) where
+instance (Serial.Write v) => Serial.Write (Nodes13 v) where
    type WriteIt (Nodes13 v) = Nodes13 (Serial.WriteIt v)
 
    insert = Serial.insertTraversable
@@ -234,8 +279,16 @@
    Value.unlift5 Interpolation.cubic a b c d r
 
 
+loadNodesExp ::
+   (C nodes, Storable am) =>
+   (Value (Ptr am) -> CodeGenFunction r a) ->
+   MultiValue.T Int ->
+   Value (Ptr am) -> CodeGenFunction r (nodes a)
+loadNodesExp loadNode (MultiValue.Cons step) =
+   MS.evalStateT $ sequenceA $ pure $ loadNext loadNode step
+
 loadNodes ::
-   (C nodes, Storable.C am) =>
+   (C nodes, Storable am) =>
    (Value (Ptr am) -> CodeGenFunction r a) ->
    Value Int ->
    Value (Ptr am) -> CodeGenFunction r (nodes a)
@@ -243,7 +296,7 @@
    MS.evalStateT $ sequenceA $ pure $ loadNext loadNode step
 
 loadNext ::
-   (Storable.C am) =>
+   (Storable am) =>
    (Value (Ptr am) -> CodeGenFunction r a) ->
    Value Int ->
    MS.StateT (Value (Ptr am)) (CodeGenFunction r) a
@@ -251,6 +304,14 @@
    MS.StateT $ \ptr -> liftA2 (,) (loadNode ptr) (Storable.advancePtr step ptr)
 
 
+
+indexNodesExp ::
+   (C nodes) =>
+   (MultiValue.T Word -> CodeGenFunction r v) ->
+   MultiValue.T Word ->
+   MultiValue.T Word -> CodeGenFunction r (nodes v)
+indexNodesExp indexNode (MultiValue.Cons step) (MultiValue.Cons offset) =
+   indexNodes (indexNode . MultiValue.Cons) step offset
 
 indexNodes ::
    (C nodes) =>
diff --git a/src/Synthesizer/LLVM/MIDI.hs b/src/Synthesizer/LLVM/MIDI.hs
--- a/src/Synthesizer/LLVM/MIDI.hs
+++ b/src/Synthesizer/LLVM/MIDI.hs
@@ -1,8 +1,7 @@
-{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE RebindableSyntax #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE Rank2Types #-}
 {- |
 Convert MIDI events of a MIDI controller to a control signal.
 -}
@@ -14,169 +13,62 @@
 
 import qualified Synthesizer.MIDI.Generic as Gen
 import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector as SerialExp
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
 
-import Synthesizer.LLVM.CausalParameterized.Process (($>))
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as Func
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.Functional as Func
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Wave as Wave
+import Synthesizer.LLVM.Causal.Process (($>))
 
-import qualified LLVM.DSL.Parameter as Param
+import LLVM.DSL.Expression (Exp)
 
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Core as LLVM
-import LLVM.Core (SizeOf)
 
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal.Number ((:*:))
-
-import qualified Algebra.RealField      as RealField
-import qualified Algebra.Additive       as Additive
-
 import Control.Arrow (second, (<<<), (<<^))
-import Control.Monad ({- liftM, -} liftM2)
 
 import NumericPrelude.Numeric
 import Prelude (($))
 
 
-{-
-{-# INLINE piecewiseConstantInit #-}
-piecewiseConstantInit ::
-   (Storable y, Tuple.Value y, Tuple.ValueOf y ~ yl,
-    Memory.C yl ym, LLVM.IsSized ym ys) =>
-   y -> EventListTT.T LazyTime y -> SigP.T p yl
-piecewiseConstantInit initial evs =
-   SigP.piecewiseConstant $#
-   (PC.subdivideInt $
-    EventListMT.consBody initial evs)
-
-
-{-# INLINE controllerLinear #-}
-controllerLinear ::
-   (Field.C y, Storable y, Tuple.Value y, Tuple.ValueOf y ~ yl,
-    Memory.C yl ym, LLVM.IsSized ym ys) =>
-   Channel -> Controller ->
-   (y,y) -> y ->
-   Filter (SigP.T p yl)
-controllerLinear chan ctrl bnd initial =
-   liftM (piecewiseConstantInit initial .
-          EventListTT.mapBody (MV.controllerLinear bnd)) $
-   getControllerEvents chan ctrl
-
-
-{-# INLINE controllerExponential #-}
-controllerExponential ::
-   (Trans.C y, Storable y, Tuple.Value y, Tuple.ValueOf y ~ yl,
-    Memory.C yl ym, LLVM.IsSized ym ys) =>
-   Channel -> Controller ->
-   (y,y) -> y ->
-   Filter (SigP.T p yl)
-controllerExponential chan ctrl bnd initial =
-   liftM (piecewiseConstantInit initial .
-          EventListTT.mapBody (MV.controllerExponential bnd)) $
-   getControllerEvents chan ctrl
-
-
-{- |
-@pitchBend channel range center@:
-emits frequencies on an exponential scale from
-@center/range@ to @center*range@.
--}
-{-# INLINE pitchBend #-}
-pitchBend ::
-   (Trans.C y, Storable y, Tuple.Value y, Tuple.ValueOf y ~ yl,
-    Memory.C yl ym, LLVM.IsSized ym ys) =>
-   Channel ->
-   y -> y ->
-   Filter (SigP.T p yl)
-pitchBend chan range center =
-   liftM (piecewiseConstantInit center .
-          EventListTT.mapBody (MV.pitchBend range center)) $
-   getSlice (maybePitchBend chan)
---   getPitchBendEvents chan
-
-{-# INLINE channelPressure #-}
-channelPressure ::
-   (Trans.C y, Storable y, Tuple.Value y, Tuple.ValueOf y ~ yl,
-    Memory.C yl ym, LLVM.IsSized ym ys) =>
-   Channel ->
-   y -> y ->
-   Filter (SigP.T p yl)
-channelPressure chan maxVal initVal =
-   liftM (piecewiseConstantInit initVal .
-          EventListTT.mapBody (MV.controllerLinear (0,maxVal))) $
-   getSlice (maybeChannelPressure chan)
-
-
-{-# INLINE bendWheelPressure #-}
-bendWheelPressure ::
-   (Ring.C a, LLVM.IsConst a,
-    RealField.C y, Trans.C y,
-    LLVM.IsConst y, SoV.Fraction y, a ~ SoV.Scalar y, SoV.Replicate y,
-    Storable y, Tuple.Value y (LLVM.Value y), LLVM.IsSized y ys) =>
-   Channel ->
-   Int -> y -> y -> y ->
-   Filter (SigP.T p (LLVM.Value y))
-bendWheelPressure chan
-     pitchRange speed wheelDepth pressDepth =
-   do bend  <- pitchBend chan
-                  (2^?(fromIntegral pitchRange/12) `asTypeOf` speed) 1
-      fm    <- controllerLinear chan VoiceMsg.modulation (0,wheelDepth) 0
-      press <- channelPressure chan pressDepth 0
-      return $
-         SigP.envelope bend $
-         SigP.mapSimple (A.add A.one) $
-         SigP.envelope
-            (SigP.mix fm press)
-            (SigP.osciSimple Wave.approxSine2 zero $# speed)
--}
-
-
 frequencyFromBendModulation ::
-   (Marshal.C y, Additive.C y, Tuple.ValueOf y ~ yl,
-    A.PseudoRing yl, A.Fraction yl, A.IntegerConstant yl) =>
-   Param.T p y ->
-   CausalP.T p (BM.T yl) yl
+   (Marshal.C y, MultiValue.T y ~ ym,
+    MultiValue.PseudoRing y, MultiValue.IntegerConstant y,
+    MultiValue.Fraction y) =>
+   Exp y -> Causal.T (BM.T ym) ym
 frequencyFromBendModulation speed =
-   frequencyFromPair SigP.osciSimple speed
+   frequencyFromPair Sig.osci speed
    <<^
    (\(BM.Cons b m) -> (b,m))
 
 
 frequencyFromBendModulationPacked ::
-   (Marshal.C a, Tuple.ValueOf a ~ LLVM.Value a,
-    Marshal.Vector n a, Tuple.VectorValueOf n a ~ LLVM.Value (LLVM.Vector n a),
-    LLVM.IsPrimitive a, LLVM.IsConst a, LLVM.IsFloating a,
-    RealField.C a, Vector.Real a, SoV.IntegerConstant a,
-    TypeNum.Positive n,
-    TypeNum.Positive (n :*: SizeOf a)) =>
-   Param.T p a ->
-   CausalP.T p (BM.T (LLVM.Value a)) (Serial.Value n a)
+   (Marshal.Vector n a) =>
+   (MultiVector.PseudoRing a, MultiVector.IntegerConstant a) =>
+   (MultiVector.Fraction a) =>
+   Exp a -> Causal.T (BM.T (MultiValue.T a)) (Serial.Value n a)
 frequencyFromBendModulationPacked speed =
-   frequencyFromPair SigPS.osciSimple speed
+   frequencyFromPair SigPS.osci speed
    <<<
-   CausalP.mapSimple
-      (\(BM.Cons b m) ->
-         liftM2 (,) (Serial.upsample b) (Serial.upsample m))
+   Causal.map (\(BM.Cons b m) -> (SerialExp.upsample b, SerialExp.upsample m))
 
 frequencyFromPair, _frequencyFromPair ::
-   (Additive.C y, A.PseudoRing yl, A.IntegerConstant yl, A.Fraction yl) =>
-   ((forall r. yl -> LLVM.CodeGenFunction r yl) ->
-    Param.T p y -> Param.T p y -> SigP.T p yl) ->
-   Param.T p y ->
-   CausalP.T p (yl,yl) yl
+   (MultiValue.Additive y,
+    A.PseudoRing ym, A.IntegerConstant ym, A.Fraction ym) =>
+   ((forall r. ym -> LLVM.CodeGenFunction r ym) ->
+    Exp y -> Exp y -> Sig.T ym) ->
+   Exp y -> Causal.T (ym,ym) ym
 frequencyFromPair osci speed =
    Func.withGuidedArgs (Func.atom, Func.atom) $ \(b, m) ->
       b * (1 + m * Func.fromSignal (osci Wave.approxSine2 zero speed))
 
 _frequencyFromPair osci speed =
-   CausalP.envelope
+   Causal.envelope
    <<<
-   second (1 + (CausalP.envelope $> osci Wave.approxSine2 zero speed))
+   second (1 + (Causal.envelope $> osci Wave.approxSine2 zero speed))
diff --git a/src/Synthesizer/LLVM/MIDI/BendModulation.hs b/src/Synthesizer/LLVM/MIDI/BendModulation.hs
--- a/src/Synthesizer/LLVM/MIDI/BendModulation.hs
+++ b/src/Synthesizer/LLVM/MIDI/BendModulation.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 {- |
 Various LLVM related instances of the BM.T type.
@@ -9,11 +10,18 @@
    BM.T(..),
    BM.deflt,
    BM.shift,
+   multiValue,
+   unMultiValue,
    ) where
 
 import qualified Synthesizer.MIDI.Value.BendModulation as BM
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
+import qualified Synthesizer.LLVM.Causal.Functional as F
 
+import qualified LLVM.DSL.Expression as Expr
+
+import qualified LLVM.Extra.Multi.Value.Storable as StorableMV
+import qualified LLVM.Extra.Multi.Value.Marshal as MarshalMV
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Vector as Vector
 import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Storable as Storable
@@ -22,20 +30,16 @@
 import qualified LLVM.Extra.Control as C
 import qualified LLVM.Core as LLVM
 
-import Control.Applicative (liftA2)
 import qualified Type.Data.Num.Decimal as TypeNum
 
+import qualified Data.Traversable as Trav
+import qualified Data.Foldable as Fold
 
-instance (Tuple.Zero a) => Tuple.Zero (BM.T a) where
-   zero = Tuple.zeroPointed
+import Control.Applicative (liftA2)
 
-{-
-instance (LLVM.ValueTuple a) => LLVM.ValueTuple (BM.T a) where
-   buildTuple f = Class.buildTupleTraversable (LLVM.buildTuple f)
 
-instance LLVM.IsTuple a => LLVM.IsTuple (BM.T a) where
-   tupleDesc = Class.tupleDescFoldable
--}
+instance (Tuple.Zero a) => Tuple.Zero (BM.T a) where
+   zero = Tuple.zeroPointed
 
 instance (Tuple.Undefined a) => Tuple.Undefined (BM.T a) where
    undef = Tuple.undefPointed
@@ -43,14 +47,40 @@
 instance (C.Select a) => C.Select (BM.T a) where
    select = C.selectTraversable
 
-{-
-instance LLVM.CmpRet a, LLVM.CmpResult a ~ b =>
-      LLVM.CmpRet (BM.T a) (BM.T b) where
--}
-
 instance Tuple.Value h => Tuple.Value (BM.T h) where
    type ValueOf (BM.T h) = BM.T (Tuple.ValueOf h)
    valueOf = Tuple.valueOfFunctor
+
+
+instance (Expr.Aggregate e mv) => Expr.Aggregate (BM.T e) (BM.T mv) where
+   type MultiValuesOf (BM.T e) = BM.T (Expr.MultiValuesOf e)
+   type ExpressionsOf (BM.T mv) = BM.T (Expr.ExpressionsOf mv)
+   bundle = Trav.traverse Expr.bundle
+   dissect = fmap Expr.dissect
+
+instance (MultiValue.C a) => MultiValue.C (BM.T a) where
+   type Repr (BM.T a) = BM.T (MultiValue.Repr a)
+   cons = multiValue . fmap MultiValue.cons
+   undef = multiValue $ pure MultiValue.undef
+   zero = multiValue $ pure MultiValue.zero
+   phi bb = fmap multiValue . Trav.traverse (MultiValue.phi bb) . unMultiValue
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb) (unMultiValue a) (unMultiValue b)
+
+instance (MarshalMV.C l) => MarshalMV.C (BM.T l) where
+   pack (BM.Cons bend depth) = MarshalMV.pack (bend, depth)
+   unpack = uncurry BM.Cons . MarshalMV.unpack
+
+instance (StorableMV.C l) => StorableMV.C (BM.T l) where
+   load = StorableMV.loadApplicative
+   store = StorableMV.storeFoldable
+
+multiValue :: BM.T (MultiValue.T a) -> MultiValue.T (BM.T a)
+multiValue = MultiValue.Cons . fmap (\(MultiValue.Cons a) -> a)
+
+unMultiValue :: MultiValue.T (BM.T a) -> BM.T (MultiValue.T a)
+unMultiValue (MultiValue.Cons x) = fmap MultiValue.Cons x
 
 
 type Struct a = LLVM.Struct (a, (a, ()))
diff --git a/src/Synthesizer/LLVM/Parameter.hs b/src/Synthesizer/LLVM/Parameter.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Parameter.hs
+++ /dev/null
@@ -1,12 +0,0 @@
-module Synthesizer.LLVM.Parameter (
-   Param.T,
-   Param.get,
-   (Param.$#),
-
-   Param.Tuple(..),
-   Param.withTuple,
-   Param.withTuple1,
-   Param.withTuple2,
-   ) where
-
-import qualified LLVM.DSL.Parameter as Param
diff --git a/src/Synthesizer/LLVM/Parameterized/Signal.hs b/src/Synthesizer/LLVM/Parameterized/Signal.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Parameterized/Signal.hs
+++ /dev/null
@@ -1,1000 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-module Synthesizer.LLVM.Parameterized.Signal (
-   T,
-   adjacentNodes02,
-   adjacentNodes13,
-   amplify,
-   amplifyStereo,
-   Sig.empty,
-   append,
-   cycle,
-   drop,
-   exponential2,
-   exponentialCore,
-   exponentialBounded2,
-   exponentialBoundedCore,
-   interpolateConstant,
-   iterate,
-   lazySize,
-   map,
-   mapSimple,
-   mapAccum,
-   Sig.mix,
-   Sig.mixExt,
-   noise,
-   noiseCore,
-   osci,
-   osciCore,
-   osciSaw,
-   osciSimple,
-   parabolaCore,
-   parabolaFadeIn,
-   parabolaFadeInInf,
-   parabolaFadeInMap,
-   parabolaFadeOut,
-   parabolaFadeOutInf,
-   parabolaFadeOutMap,
-   piecewiseConstant,
-   ramp,
-   rampCore,
-   rampInf,
-   rampSlope,
-   reparameterize,
-   tail,
-   constant,
-   Sig.envelope,
-   Sig.envelopeStereo,
-   simple,
-   zip,
-   zipWith,
-   zipWithSimple,
-
-   fromStorableVector,
-   fromStorableVectorLazy,
-
-   render,
-   renderChunky,
-   run,
-   runChunky,
-   runChunkyPattern,
-   runChunkyPlugged,
-
-   -- for testing
-   noiseCoreAlt,
-   ) where
-
-import Synthesizer.LLVM.Parameterized.SignalPrivate
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as SigPriv
-import qualified Synthesizer.LLVM.Simple.Signal as Sig
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPrivate as CausalP
-import qualified Synthesizer.LLVM.Causal.Process as Causal
-import qualified Synthesizer.LLVM.Plug.Output as POut
-import qualified Synthesizer.LLVM.Interpolation as Interpolation
-import qualified Synthesizer.LLVM.ConstantPiece as Const
-import Synthesizer.Causal.Class (($*), ($<))
-
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Frame as Frame
-import qualified Synthesizer.LLVM.Random as Rnd
-import qualified Synthesizer.LLVM.Wave as Wave
-import qualified Synthesizer.LLVM.ForeignPtr as ForeignPtr
-
-import qualified Synthesizer.LLVM.Storable.ChunkIterator as ChunkIt
-import qualified Synthesizer.LLVM.Storable.Vector as SVU
-import qualified Data.StorableVector.Lazy.Pattern as SVP
-import qualified Data.StorableVector.Lazy as SVL
-import qualified Data.StorableVector as SV
-import qualified Data.StorableVector.Base as SVB
-
-import qualified Data.EventList.Relative.BodyTime as EventList
-import qualified Numeric.NonNegative.Chunky as Chunky
-import qualified Numeric.NonNegative.Wrapper as NonNeg
-
-import qualified LLVM.DSL.Execution as Exec
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Tuple as Tuple
-import LLVM.Extra.Control (whileLoop)
-
-import qualified LLVM.ExecutionEngine as EE
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-          (CodeGenFunction, ret, Value, value, valueOf,
-           IsSized, IsConst, IsArithmetic, IsFloating,
-           CodeGenModule, Function)
-
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import Control.Monad.HT ((<=<))
-import Control.Monad (when)
-import Control.Arrow ((^<<))
-import Control.Applicative (Applicative, liftA2, liftA3, pure, (<$>))
-import Control.Functor.HT (void)
-
-import qualified Algebra.Transcendental as Trans
-import qualified Algebra.RealField as RealField
-import qualified Algebra.Algebraic as Algebraic
-import qualified Algebra.Field as Field
-import qualified Algebra.Additive as Additive
-
-import Data.Functor.Compose (Compose(Compose))
-import Data.Tuple.HT (mapSnd)
-import Data.Word (Word8, Word32, Word)
-import Data.Int (Int32)
-
-import Foreign.ForeignPtr (touchForeignPtr)
-import Foreign.Ptr (Ptr, nullPtr)
-import Control.Exception (bracket)
-import qualified System.Unsafe as Unsafe
-
-import qualified LLVM.DSL.Debug.Marshal as DebugSt
-import qualified LLVM.DSL.Debug.Counter as Counter
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base hiding (and, tail, iterate, map, zip, zipWith, cycle, drop)
-
-
-reparameterize :: Param.T q p -> T p a -> T q a
-reparameterize p (Cons start alloca stop next create delete) =
-   Cons start alloca stop next (create . Param.get p) delete
-
-
--- * timeline edit
-
-{- |
-@tail empty@ generates the empty signal.
--}
-tail :: T p a -> T p a
-tail (Cons next alloca start stop createIOContext deleteIOContext) = Cons
-   next
-   alloca
-   (\parameter -> do
-      local <- alloca
-      (c,s0) <- start parameter
-      MaybeCont.resolve (next c local s0)
-         (return (c,s0))
-         (\(_a,s1) -> return (c,s1)))
-   stop
-   createIOContext
-   deleteIOContext
-
-drop :: Param.T p Int -> T p a -> T p a
-drop n (Cons next alloca start stop createIOContext deleteIOContext) =
-   Param.withValue (Param.wordInt n) $ \getN valueN -> Cons
-   next
-   alloca
-   (\(parameter, i0) -> do
-      local <- alloca
-      (c,s0) <- start parameter
-      (_, _, s3) <-
-         whileLoop (valueOf True, valueN i0, s0)
-            (\(cont,i1,_s1) ->
-               A.and cont =<<
-                  A.cmp LLVM.CmpGT i1 A.zero)
-            (\(_cont,i1,s1) -> do
-               (cont, s2) <-
-                  MaybeCont.resolve (next c local s1)
-                     (return (valueOf False, s1))
-                     (\(_a,s) -> return (valueOf True, s))
-               i2 <- A.dec i1
-               return (cont, i2, s2))
-      return (c, s3))
-   stop
-   (\p -> do
-      (ioContext, param) <- createIOContext p
-      return (ioContext, (param, getN p)))
-   deleteIOContext
-
-
-cycle ::
-   (Tuple.Phi a, Tuple.Undefined a) =>
-   T p a -> T p a
-cycle (Cons next alloca start stop createIOContext deleteIOContext) =
-   Cons
-      (\parameter local (c0,s0) ->
-          MaybeCont.alternative
-             (fmap (mapSnd ((,) c0)) $ next c0 local s0)
-             (do (c1,s1) <- MaybeCont.lift $ start parameter
-                 (b0,s2) <- next c1 local s1
-                 return (b0,(c1,s2))))
-      alloca
-      (\parameter -> do
-         contextState <- start parameter
-         return (parameter, contextState))
-      (\_parameter contextState -> uncurry stop contextState)
-      createIOContext
-      deleteIOContext
-
-
--- * signal modifiers
-
-{- |
-Stretch signal in time by a certain factor.
-
-This can be used for doing expensive computations
-of filter parameters at a lower rate.
-Alternatively, we could provide an adaptive @map@
-that recomputes output values only if the input value changes,
-or if the input value differs from the last processed one by a certain amount.
--}
-interpolateConstant ::
-   (Memory.C a,
-    IsFloating b, SoV.IntegerConstant b, LLVM.CmpRet b, LLVM.CmpResult b ~ Bool,
-    Marshal.C b, Tuple.ValueOf b ~ Value b) =>
-   Param.T p b -> T p a -> T p a
-interpolateConstant k sig =
-   CausalP.toSignal
-      (Causal.quantizeLift (CausalP.fromSignal sig) $< constant k)
-
-
-amplify ::
-   (A.PseudoRing al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p al -> T p al
-amplify =
-   map Frame.amplifyMono
-
-amplifyStereo ::
-   (A.PseudoRing al, Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p a -> T p (Stereo.T al) -> T p (Stereo.T al)
-amplifyStereo =
-   map Frame.amplifyStereo
-
-
-mapAccum ::
-   (Marshal.C pnh, Tuple.ValueOf pnh ~ pnl,
-    Marshal.C psh, Tuple.ValueOf psh ~ psl, Memory.C s) =>
-   (forall r. pnl -> a -> s -> CodeGenFunction r (b,s)) ->
-   (forall r. psl -> CodeGenFunction r s) ->
-   Param.T p pnh ->
-   Param.T p psh ->
-   T p a -> T p b
-mapAccum next start n s xs =
-   CausalP.mapAccum next start n s $* xs
-
-adjacentNodes02 ::
-   (Memory.C a, Tuple.Undefined a) =>
-   T p a -> T p (Interpolation.Nodes02 a)
-adjacentNodes02 =
-   tail
-   .
-   Sig.mapAccum
-      (\new old -> return (Interpolation.Nodes02 old new, new))
-      (return Tuple.undef)
-
-adjacentNodes13 ::
-   (Marshal.C ah, Tuple.ValueOf ah ~ a, Tuple.Undefined a) =>
-   Param.T p ah -> T p a -> T p (Interpolation.Nodes13 a)
-adjacentNodes13 yp0 =
-   tail .
-   tail .
-   mapAccum
-      (\() new (x0, x1, x2) ->
-         return (Interpolation.Nodes13 x0 x1 x2 new, (x1, x2, new)))
-      (\y0 -> return (Tuple.undef, Tuple.undef, Param.valueTuple yp0 y0))
-      (pure ()) yp0
-
-
-
--- * signal generators
-
-
-exponentialCore ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, A.PseudoRing al) =>
-   Param.T p a -> Param.T p a -> T p al
-exponentialCore =
-   iterate A.mul
-
-exponential2 ::
-   (Trans.C a, Marshal.C a, Tuple.ValueOf a ~ Value a,
-    IsArithmetic a, IsConst a) =>
-   Param.T p a -> Param.T p a -> T p (Value a)
-exponential2 halfLife =
-   exponentialCore (0.5 ** recip halfLife)
-
-
-exponentialBoundedCore ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, A.PseudoRing al, A.Real al) =>
-   Param.T p a -> Param.T p a -> Param.T p a ->
-   T p al
-exponentialBoundedCore bound decay =
-   iterate
-      (\(b,k) y -> A.max b =<< A.mul k y)
-      (liftA2 (,) bound decay)
-
-{- |
-Exponential curve that remains at the bound value
-if it would fall below otherwise.
-This way you can avoid extremal values, e.g. denormalized ones.
-The initial value and the bound value must be positive.
--}
-exponentialBounded2 ::
-   (Trans.C a, Marshal.C a, Tuple.ValueOf a ~ Value a, SoV.Real a, IsConst a) =>
-   Param.T p a -> Param.T p a -> Param.T p a ->
-   T p (Value a)
-exponentialBounded2 bound halfLife =
-   exponentialBoundedCore bound (0.5 ** recip halfLife)
-
-
-osciCore ::
-   (Marshal.C t, Tuple.ValueOf t ~ tl, A.Fraction tl) =>
-   Param.T p t -> Param.T p t -> T p tl
-osciCore phase freq =
-   iterate A.incPhase freq phase
-
-osci ::
-   (Marshal.C t, Tuple.ValueOf t ~ tl, A.Fraction tl, A.IntegerConstant tl,
-    Marshal.C c, Tuple.ValueOf c ~ cl) =>
-   (forall r. cl -> tl -> CodeGenFunction r y) ->
-   Param.T p c ->
-   Param.T p t -> Param.T p t -> T p y
-osci wave waveParam phase freq =
-   map wave waveParam $ osciCore phase freq
-
-osciSimple ::
-   (Marshal.C t, Tuple.ValueOf t ~ tl, A.Fraction tl, A.IntegerConstant tl) =>
-   (forall r. tl -> CodeGenFunction r y) ->
-   Param.T p t -> Param.T p t -> T p y
-osciSimple wave phase freq =
-   Sig.map wave $ osciCore phase freq
-
-osciSaw ::
-   (Marshal.C a, Tuple.ValueOf a ~ al,
-    A.PseudoRing al, A.Fraction al, A.IntegerConstant al) =>
-   Param.T p a -> Param.T p a -> T p al
-osciSaw =
-   osciSimple Wave.saw
-
-
-
-rampCore ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, A.Additive al, A.IntegerConstant al) =>
-   Param.T p a -> Param.T p a -> T p al
-rampCore = iterate A.add
-
-parabolaCore ::
-   (Marshal.C a, Tuple.ValueOf a ~ al, A.Additive al, A.IntegerConstant al) =>
-   Param.T p a -> Param.T p a -> Param.T p a -> T p al
-parabolaCore d2 d1 start =
-   CausalP.apply (CausalP.integrate start) $
-   rampCore d2 d1
-
-
-
-rampInf, rampSlope,
- parabolaFadeInInf, parabolaFadeOutInf ::
-   (Field.C a,
-    Marshal.C a, Tuple.ValueOf a ~ al, A.Additive al, A.IntegerConstant al) =>
-   Param.T p a -> T p al
-rampSlope slope  =  rampCore slope Additive.zero
-rampInf dur  =  rampSlope (recip dur)
-
-{-
-t*(2-t) = 1 - (t-1)^2
-
-(t+d)*(2-t-d) - t*(2-t)
-   = d*(2-t) - d*t - d^2
-   = 2*d*(1-t) - d^2
-   = d*(2*(1-t) - d)
-
-2*d*(1-t-d) + d^2  -  (2*d*(1-t) + d^2)
-   = -2*d^2
--}
-parabolaFadeInInf dur =
-   parabolaCore
-      (fmap (\d -> -2*d*d)  $ recip dur)
-      (fmap (\d -> d*(2-d)) $ recip dur)
-      Additive.zero
-
-{-
-1-t^2
--}
-parabolaFadeOutInf dur =
-   parabolaCore
-      (fmap (\d -> -2*d*d) $ recip dur)
-      (fmap (\d ->   -d*d) $ recip dur)
-      one
-
-ramp,
- parabolaFadeIn, parabolaFadeOut,
- parabolaFadeInMap, parabolaFadeOutMap ::
-   (RealField.C a, Marshal.C a, Tuple.ValueOf a ~ al,
-    A.PseudoRing al, A.IntegerConstant al) =>
-   Param.T p a -> T p al
-
-ramp dur =
-   CausalP.apply (CausalP.take (fmap round dur)) $
-   rampInf dur
-
-parabolaFadeIn dur =
-   CausalP.apply (CausalP.take (fmap round dur)) $
-   parabolaFadeInInf dur
-
-parabolaFadeOut dur =
-   CausalP.apply (CausalP.take (fmap round dur)) $
-   parabolaFadeOutInf dur
-
-parabolaFadeInMap dur =
-   -- t*(2-t)
-   CausalP.apply (CausalP.mapSimple (\t -> A.mul t =<< A.sub (A.fromInteger' 2) t)) $
-   ramp dur
-
-parabolaFadeOutMap dur =
-   -- 1-t^2
-   CausalP.apply (CausalP.mapSimple (\t -> A.sub (A.fromInteger' 1) =<< A.mul t t)) $
-   ramp dur
-
-
-{- |
-@noise seed rate@
-
-The @rate@ parameter is for adjusting the amplitude
-such that it is uniform across different sample rates
-and after frequency filters.
-The @rate@ is the ratio of the current sample rate to the default sample rate,
-where the variance of the samples would be one.
-If you want that at sample rate 22050 the variance is 1,
-then in order to get a consistent volume at sample rate 44100
-you have to set @rate = 2@.
-
-I use the variance as quantity and not the amplitude,
-because the amplitude makes only sense for uniformly distributed samples.
-However, frequency filters transform the probabilistic density of the samples
-towards the normal distribution according to the central limit theorem.
--}
-noise ::
-   (Algebraic.C a, IsFloating a, IsConst a, Marshal.C a,
-    Tuple.ValueOf a ~ Value a, LLVM.IsPrimitive a) =>
-   Param.T p Word32 ->
-   Param.T p a ->
-   T p (Value a)
-noise seed rate =
-   let m2 = fromInteger $ div Rnd.modulus 2
-   in  map (\r y ->
-          A.mul r
-           =<< flip A.sub (valueOf $ m2+1)
-           =<< int31tofp y)
-          (sqrt (3 * rate) / return m2) $
-       noiseCore seed
-
-{-
-sitofp is a single instruction on x86
-and thus we use it, since the arguments are below 2^31.
--}
-int31tofp ::
-   (IsFloating a, LLVM.ShapeOf a ~ LLVM.ScalarShape) =>
-   Value Word32 -> CodeGenFunction r (Value a)
-int31tofp =
-   LLVM.inttofp <=<
-   (LLVM.bitcast ::
-       Value Word32 -> CodeGenFunction r (Value Int32))
-
-noiseCore, noiseCoreAlt ::
-   Param.T p Word32 ->
-   T p (Value Word32)
-noiseCore seed =
-   iterate (const Rnd.nextCG)
-      (return ()) ((+1) . flip mod (Rnd.modulus-1) ^<< seed)
-
-noiseCoreAlt seed =
-   iterate (const Rnd.nextCG32)
-      (return ()) ((+1) . flip mod (Rnd.modulus-1) ^<< seed)
-
-
--- * conversion from and to storable vectors
-
-fromStorableVector ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   Param.T p (SV.Vector a) ->
-   T p value
-fromStorableVector selectVec =
-   Cons
-      (\() () (p0,l0) -> do
-         cont <- MaybeCont.lift $ A.cmp LLVM.CmpGT l0 A.zero
-         MaybeCont.withBool cont $ do
-            y1 <- Storable.load p0
-            p1 <- Storable.incrementPtr p0
-            l1 <- A.dec l0
-            return (y1,(p1,l1)))
-      (return ())
-      (return . (,) ())
-      (\() _ -> return ())
-      (\p ->
-         let (fp,ptr,l) = SVU.unsafeToPointers $ Param.get selectVec p
-         in  return (fp, (ptr, fromIntegral l :: Word)))
-      -- keep the foreign ptr alive
-      touchForeignPtr
-
-{-
-This function calls back into the Haskell function 'ChunkIt.next'
-that returns a pointer to the data of the next chunk
-and advances to the next chunk in the sequence.
--}
-fromStorableVectorLazy ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   Param.T p (SVL.Vector a) -> T p value
-fromStorableVectorLazy = SigPriv.flattenChunks . storableVectorChunks
-
-storableVectorChunks ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   Param.T p (SVL.Vector a) ->
-   T p (Value (Ptr a), Value Word)
-storableVectorChunks sig =
-   Cons
-      (SigPriv.storableVectorNextChunk
-         "Parameterized.Signal.fromStorableVectorLazy.nextChunk")
-      LLVM.alloca
-      (\s -> return (s, ()))
-      (\ _s _ -> return ())
-      (\p -> do
-          s <- ChunkIt.new (Param.get sig p)
-          return (s, s))
-      ChunkIt.dispose
-
-
-
-piecewiseConstant ::
-   (Marshal.C a, Tuple.ValueOf a ~ value) =>
-   Param.T p (EventList.T NonNeg.Int a) ->
-   T p value
-piecewiseConstant =
-   Const.flatten . Const.piecewiseConstant
-
-
-
-{- |
-Turns a lazy chunky size into a signal generator with unit element type.
-The signal length is the only information that the generator provides.
-Using 'zipWith' you can use this signal as a lazy 'take'.
--}
-lazySize ::
-   Param.T p SVP.LazySize ->
-   T p ()
-lazySize =
-   Const.flatten . Const.lazySize
-
-
-
-createFunction ::
-   (Functor genMod, EE.ExecutionFunction fun) =>
-   Exec.Importer fun -> genMod (Function fun) ->
-   Compose genMod EE.EngineAccess fun
-createFunction importer modul =
-   Compose $ EE.getExecutionFunction importer <$> modul
-
-createFinalizer ::
-   (Applicative genMod, EE.ExecutionFunction fun) =>
-   Exec.Importer fun -> genMod (Function fun) ->
-   Compose genMod EE.EngineAccess (EE.ExecutionEngine, fun)
-createFinalizer importer modul =
-   liftA2 (,)
-      (Compose $ pure EE.getEngine)
-      (createFunction importer modul)
-
-
-foreign import ccall safe "dynamic" derefFillPtr ::
-   Exec.Importer (LLVM.Ptr param -> Word -> Ptr a -> IO Word)
-
-
-moduleFill ::
-   (Storable.C a, Tuple.ValueOf a ~ value,
-    Memory.C parameters, Memory.Struct parameters ~ paramStruct,
-    Tuple.Phi state, Tuple.Undefined state) =>
-   (forall r z.
-    (Tuple.Phi z) =>
-    context -> local -> state -> MaybeCont.T r z (value, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r.
-    parameters -> CodeGenFunction r (context, state)) ->
-   (forall r.
-    context -> state -> CodeGenFunction r ()) ->
-   CodeGenModule
-      (Function (LLVM.Ptr paramStruct -> Word -> Ptr a -> IO Word))
-moduleFill next alloca start stop =
-   Exec.createLLVMFunction "fillsignalblock" $
-   \paramPtr size bPtr -> do
-      param <- Memory.load paramPtr
-      (c,s) <- start param
-      local <- alloca
-      (pos,se) <- Storable.arrayLoopMaybeCont size bPtr s $ \ ptri s0 -> do
-         (y,s1) <- next c local s0
-         MaybeCont.lift $ Storable.store y ptri
-         return s1
-      Maybe.for se $ stop c
-      ret pos
-
-
-declareMallocBytes :: LLVM.TFunction (Ptr Word8 -> IO (Ptr a))
-declareMallocBytes = LLVM.newNamedFunction LLVM.ExternalLinkage "malloc"
-
-debugMain ::
-   forall parameters a paramStruct.
-   (Marshal.C parameters,
-    Storable.C a,
-    LLVM.IsType paramStruct, IsSized paramStruct) =>
-   CodeGenModule
-      (Function (LLVM.Ptr paramStruct -> Word -> Ptr a -> IO Word)) ->
-   parameters ->
-   IO (Function (Word -> Ptr (Ptr Word8) -> IO Word))
-debugMain sigModule params = do
-   paramArray <-
-      DebugSt.withConstArray params (\arr -> do
-         ptr <- LLVM.alloca
-         LLVM.store (value arr) =<< LLVM.bitcast ptr
-         return ptr)
-
-   m <- LLVM.newModule
-
-   mainFunc <- LLVM.defineModule m (do
-      LLVM.setTarget LLVM.hostTriple
-      mallocBytes <- declareMallocBytes
-      fill <- sigModule
-      Exec.createLLVMFunction "main" $ \ _argc _argv -> do
-         paramPtr <- paramArray
-         let chunkSize = 100000
-             basePtr = LLVM.valueOf nullPtr
-         buffer <-
-            LLVM.call mallocBytes =<<
-            LLVM.bitcast =<<
-            Storable.advancePtr
-               (LLVM.valueOf chunkSize) (basePtr :: LLVM.Value (Ptr a))
-         _done <-
-            LLVM.call fill paramPtr
-               (LLVM.valueOf $ fromIntegral chunkSize)
-               (asTypeOf buffer basePtr)
-         ret (A.zero :: LLVM.Value Word))
-
-   Exec.dumper "main" >>= \writeBitcodeToFile -> writeBitcodeToFile "" m
-
-   return mainFunc
-
-
-run ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   T p value ->
-   IO (Int -> p -> SV.Vector a)
-run (Cons next alloca start stop createIOContext deleteIOContext) =
-   do -- this compiles once and is much faster than simpleFunction
-      let modul = moduleFill next alloca start stop
-      fill <- Exec.compile "signal" $ createFunction derefFillPtr modul
-
-      return $ \len p ->
-         Unsafe.performIO $
-         bracket (createIOContext p) (deleteIOContext . fst) $
-         \ (_,params) -> do
-            when False $ void $ debugMain modul params
-
-            SVB.createAndTrim len $ \ ptr ->
-               Marshal.with params $ \paramPtr ->
-               fmap fromIntegral $ fill paramPtr (fromIntegral len) ptr
-
-{- |
-This is not really a function, see 'renderChunky'.
--}
-render ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   T p value -> Int -> p -> SV.Vector a
-render gen = Unsafe.performIO $ run gen
-
-
-foreign import ccall safe "dynamic" derefStartPtr ::
-   Exec.Importer (LLVM.Ptr b -> IO (LLVM.Ptr a))
-
-foreign import ccall safe "dynamic" derefStopPtr ::
-   Exec.Importer (LLVM.Ptr a -> IO ())
-
-foreign import ccall safe "dynamic" derefChunkPtr ::
-   Exec.Importer (LLVM.Ptr contextStateStruct -> Word -> Ptr a -> IO Word)
-
-foreign import ccall safe "dynamic" derefChunkPluggedPtr ::
-   Exec.Importer
-      (LLVM.Ptr contextStateStruct -> Word -> LLVM.Ptr struct -> IO Word)
-
-
-moduleStart ::
-   (Memory.C parameters, Memory.Struct parameters ~ paramStruct,
-    Memory.C context, Memory.C state,
-    Memory.Struct (context, Maybe.T state) ~ contextStateStruct) =>
-   (forall r. parameters -> CodeGenFunction r (context, state)) ->
-   CodeGenModule (Function
-      (LLVM.Ptr paramStruct -> IO (LLVM.Ptr contextStateStruct)))
-moduleStart start =
-   Exec.createLLVMFunction "startsignal" $
-   \paramPtr -> do
-      pptr <- LLVM.malloc
-      flip Memory.store pptr . mapSnd Maybe.just
-         =<< start =<< Memory.load paramPtr
-      ret pptr
-
-moduleStop ::
-   (Memory.C context, Memory.C state,
-    Memory.Struct (context, Maybe.T state) ~ contextStateStruct) =>
-   (forall r. context -> state -> CodeGenFunction r ()) ->
-   CodeGenModule (Function (LLVM.Ptr contextStateStruct -> IO ()))
-moduleStop stop =
-   Exec.createLLVMFunction "stopsignal" $
-   \contextStatePtr -> do
-      (c,ms) <- Memory.load contextStatePtr
-      Maybe.for ms $ stop c
-      LLVM.free contextStatePtr
-      ret ()
-
-moduleNext ::
-   (Storable.C a, Tuple.ValueOf a ~ value,
-    Memory.C context, Memory.C state,
-    Memory.Struct (context, Maybe.T state) ~ contextStateStruct,
-    Tuple.Phi state, Tuple.Undefined state) =>
-   (forall r z.
-    (Tuple.Phi z) =>
-    context -> local -> state -> MaybeCont.T r z (value, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   CodeGenModule
-      (Function (LLVM.Ptr contextStateStruct -> Word -> Ptr a -> IO Word))
-moduleNext next alloca =
-   Exec.createLLVMFunction "fillsignal" $
-   \contextStatePtr loopLen ptr -> do
-      (context, msInit) <- Memory.load contextStatePtr
-      local <- alloca
-      (pos,msExit) <-
-         Maybe.run msInit (return (A.zero, Maybe.nothing)) $ \sInit ->
-            Storable.arrayLoopMaybeCont loopLen ptr sInit $ \ptri s0 -> do
-         (y,s1) <- next context local s0
-         MaybeCont.lift $ Storable.store y ptri
-         return s1
-      sptr <- LLVM.getElementPtr0 contextStatePtr (TypeNum.d1, ())
-      Memory.store msExit sptr
-      ret pos
-
-moduleNextPlugged ::
-   (Memory.C context, Memory.C state,
-    Memory.Struct (context, Maybe.T state) ~ contextStateStruct,
-    Tuple.Undefined stateOut, Tuple.Phi stateOut,
-    Memory.C paramValueOut, Memory.Struct paramValueOut ~ paramStructOut) =>
-   (forall r z.
-    (Tuple.Phi z) =>
-    context -> local -> state -> MaybeCont.T r z (value, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r.
-    paramValueOut ->
-    value -> stateOut -> LLVM.CodeGenFunction r stateOut) ->
-   (forall r.
-    paramValueOut ->
-    LLVM.CodeGenFunction r stateOut) ->
-   CodeGenModule
-      (Function
-         (LLVM.Ptr contextStateStruct -> Word ->
-          LLVM.Ptr paramStructOut -> IO Word))
-moduleNextPlugged next alloca nextOut startOut =
-   Exec.createLLVMFunction "fillsignal" $
-   \contextStatePtr loopLen outPtr -> do
-      (context, msInit) <- Memory.load contextStatePtr
-      outParam <- Memory.load outPtr
-      outInit <- startOut outParam
-      local <- alloca
-      (pos,msExit) <-
-         Maybe.run msInit (return (A.zero, Maybe.nothing)) $ \sInit ->
-            MaybeCont.fixedLengthLoop loopLen (sInit, outInit) $
-               \ (s0,out0) -> do
-         (y,s1) <- next context local s0
-         out1 <- MaybeCont.lift $ nextOut outParam y out0
-         return (s1, out1)
-      sptr <- LLVM.getElementPtr0 contextStatePtr (TypeNum.d1, ())
-      Memory.store (fmap fst msExit) sptr
-      ret pos
-
-debugChunkyMain ::
-   forall parameters a paramStruct contextStateStruct.
-   (Marshal.C parameters,
-    Storable.C a,
-    LLVM.IsType contextStateStruct,
-    LLVM.IsType paramStruct, IsSized paramStruct) =>
-   CodeGenModule
-      (Function (LLVM.Ptr paramStruct -> IO (LLVM.Ptr contextStateStruct)),
-       Function (LLVM.Ptr contextStateStruct -> IO ()),
-       Function (LLVM.Ptr contextStateStruct ->
-                 Word -> Ptr a -> IO Word)) ->
-   parameters ->
-   IO (Function (Word -> Ptr (Ptr Word8) -> IO Word))
-debugChunkyMain sigModule params = do
-{-
-This does not work, since we cannot add (Mul n D32 s) constraint
-to the function argument in reifyIntegral.
-   nextArray <-
-      DebugSt.withConstArray nextParam (\arr -> do
-         ptr <- LLVM.alloca
-         LLVM.store (value arr) ptr
-         LLVM.bitcast ptr)
--}
-   paramArray <-
-      DebugSt.withConstArray params (\arr -> do
-         ptr <- LLVM.alloca
-         LLVM.store (value arr) =<< LLVM.bitcast ptr
-         return ptr)
-
-   m <- LLVM.newModule
-
-   mainFunc <- LLVM.defineModule m (do
-      LLVM.setTarget LLVM.hostTriple
-      mallocBytes <- declareMallocBytes
-      (start, stop, fill) <- sigModule
-      Exec.createLLVMFunction "main" $ \ _argc _argv -> do
-         contextState <- LLVM.call start =<< paramArray
-         let chunkSize = 100000
-             basePtr = LLVM.valueOf nullPtr
-         buffer <-
-            LLVM.call mallocBytes =<<
-            LLVM.bitcast =<<
-            Storable.advancePtr
-               (LLVM.valueOf chunkSize) (basePtr :: LLVM.Value (Ptr a))
-         _done <-
-            LLVM.call fill contextState
-               (LLVM.valueOf $ fromIntegral chunkSize)
-               (asTypeOf buffer basePtr)
-         _ <- LLVM.call stop contextState
-         ret (A.zero :: LLVM.Value Word))
-
-   Exec.dumper "main-chunky" >>= \writeBitcodeToFile -> writeBitcodeToFile "" m
-
-   return mainFunc
-
-
-
-{- |
-Renders a signal generator to a chunky storable vector with given pattern.
-If the pattern is shorter than the generated signal
-this means that the signal is shortened.
--}
-runChunkyPattern, _runChunkyPattern ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   T p value ->
-   IO (SVP.LazySize -> p -> SVL.Vector a)
-_runChunkyPattern =
-   fmap (\f size -> SVL.fromChunks . f size) .
-   flip runChunkyPatternPlugged POut.deflt
-
-runChunkyPattern
-      (Cons next alloca start stop createIOContext deleteIOContext) = do
-
-   let startF = moduleStart start
-   let stopF = moduleStop stop
-   let nextF = moduleNext next alloca
-
-   (startFunc, stopFunc, fill) <-
-      Exec.compile "signal-pattern" $
-      liftA3 (,,)
-         (createFunction derefStartPtr startF)
-         (createFinalizer derefStopPtr stopF)
-         (createFunction derefChunkPtr nextF)
-
-   return $
-      \ lazysize p -> SVL.fromChunks $ Unsafe.performIO $ do
-         (ioContext, param) <- createIOContext p
-
-{-
-         putStr "nextParam: "
-         DebugSt.format nextParam >>= putStrLn
--}
-         when False $
-            Counter.next DebugSt.dumpCounter >>=
-            DebugSt.dump "param" param
-
-         when False $ void $
-            debugChunkyMain (liftA3 (,,) startF stopF nextF) param
-
-         statePtr <- ForeignPtr.newParam stopFunc startFunc param
-         ioContextPtr <- ForeignPtr.newAux (deleteIOContext ioContext)
-
-         let go cs =
-                Unsafe.interleaveIO $
-                case cs of
-                   [] -> return []
-                   SVL.ChunkSize size : rest -> do
-                      v <-
-                         ForeignPtr.with statePtr $ \sptr ->
-                         SVB.createAndTrim size $
-                         fmap fromIntegral .
-                         fill sptr (fromIntegral size)
-                      touchForeignPtr ioContextPtr
-                      (if SV.length v > 0
-                         then fmap (v:)
-                         else id) $
-                         (if SV.length v < size
-                            then return []
-                            else go rest)
-         go (Chunky.toChunks lazysize)
-
-runChunkyPatternPlugged ::
-   T p value ->
-   POut.T value chunk ->
-   IO (SVP.LazySize -> p -> [chunk])
-runChunkyPatternPlugged
-      (Cons next alloca start stop createIOContext deleteIOContext)
-      (POut.Cons nextOut startOut createOut deleteOut) = do
-
-   (startFunc, stopFunc, fill) <-
-      Exec.compile "signal-plugged" $
-      liftA3 (,,)
-         (createFunction derefStartPtr $ moduleStart start)
-         (createFinalizer derefStopPtr $ moduleStop stop)
-         (createFunction derefChunkPluggedPtr $
-          moduleNextPlugged next alloca nextOut startOut)
-
-   return $
-      \ lazysize p -> Unsafe.performIO $ do
-         (ioContext, param) <- createIOContext p
-
-         statePtr <- ForeignPtr.newParam stopFunc startFunc param
-         ioContextPtr <- ForeignPtr.newAux (deleteIOContext ioContext)
-
-         let go cs =
-                Unsafe.interleaveIO $
-                case cs of
-                   [] -> return []
-                   SVL.ChunkSize maximumSize : rest -> do
-                      (contextOut,paramOut) <- createOut maximumSize
-                      actualSize <-
-                         fmap fromIntegral $
-                         Marshal.with paramOut $ \outptr ->
-                         ForeignPtr.with statePtr $ \sptr ->
-                         fill sptr (fromIntegral maximumSize) outptr
-                      when (fromIntegral actualSize > maximumSize) $
-                         error $ "Parametrized.Signal: " ++
-                                 "output size " ++ show actualSize ++
-                                 " > input size " ++ show maximumSize
-                      v <- deleteOut actualSize contextOut
-                      touchForeignPtr ioContextPtr
-                      (if actualSize > 0
-                         then fmap (v:)
-                         else id) $
-                         (if actualSize < maximumSize
-                            then return []
-                            else go rest)
-         go (Chunky.toChunks lazysize)
-
-runChunky, _runChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   T p value ->
-   IO (SVL.ChunkSize -> p -> SVL.Vector a)
-runChunky sig =
-   flip fmap (runChunkyPattern sig) $ \f size p ->
-      f (Chunky.fromChunks (repeat size)) p
-
-_runChunky =
-   fmap (\f size -> SVL.fromChunks . f size) .
-   flip runChunkyPlugged POut.deflt
-
-runChunkyPlugged ::
-   T p value ->
-   POut.T value chunk ->
-   IO (SVL.ChunkSize -> p -> [chunk])
-runChunkyPlugged sig plug =
-   flip fmap (runChunkyPatternPlugged sig plug) $ \f size p ->
-      f (Chunky.fromChunks (repeat size)) p
-
-{- |
-This looks like a function,
-but it is not a function since it depends on LLVM being initialized
-with LLVM.initializeNativeTarget before.
-It is also problematic since you cannot control when and how often
-the underlying LLVM code is compiled.
-The compilation cannot be observed, thus it is referential transparent.
-But this influences performance considerably
-and I assume that you use this package exclusively for performance reasons.
--}
-renderChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   SVL.ChunkSize -> T p value ->
-   p -> SVL.Vector a
-renderChunky size gen =
-   Unsafe.performIO (runChunky gen) size
diff --git a/src/Synthesizer/LLVM/Parameterized/SignalPacked.hs b/src/Synthesizer/LLVM/Parameterized/SignalPacked.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Parameterized/SignalPacked.hs
+++ /dev/null
@@ -1,287 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE FlexibleContexts #-}
-{- |
-Signal generators that generate the signal in chunks
-that can be processed natively by the processor.
-Some of the functions for plain signals can be re-used without modification.
-E.g. rendering a signal and reading from and to signals work
-because the vector type as element type warrents correct alignment.
-We can convert between atomic and chunked signals.
-
-The article
-<http://perilsofparallel.blogspot.com/2008/09/larrabee-vs-nvidia-mimd-vs-simd.html>
-explains the difference between Vector and SIMD computing.
-According to that the SSE extensions in Intel processors
-must be called Vector computing.
-But since we use the term Vector already in the mathematical sense,
-I like to use the term "packed" that is used in Intel mnemonics like mulps.
--}
-module Synthesizer.LLVM.Parameterized.SignalPacked (
-   SigS.pack, SigS.packRotate,
-   SigS.packSmall,
-   SigS.unpack, SigS.unpackRotate,
-   constant,
-   exponential2,
-   exponentialBounded2,
-   osciCore,
-   osci,
-   osciSimple,
-   parabolaFadeInInf, parabolaFadeOutInf,
-   rampInf, rampSlope,
-   noise,
-   noiseCore, noiseCoreAlt,
-   ) where
-
-import Synthesizer.LLVM.Parameterized.Signal (T)
-import qualified Synthesizer.LLVM.Simple.SignalPacked as SigS
-import qualified Synthesizer.LLVM.Parameterized.Signal as Sig
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Random as Rnd
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal ((:*:))
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-         (CodeGenFunction, Value,
-          IsConst, IsArithmetic, IsFloating, IsPrimitive, Vector, SizeOf)
-
-import Control.Monad.HT ((<=<))
--- we can also use <$> for parameters
-import Control.Arrow ((^<<))
-import Control.Applicative (liftA2)
-
-import qualified Algebra.Transcendental as Trans
-import qualified Algebra.Algebraic as Algebraic
-import qualified Algebra.RealField as RealField
-import qualified Algebra.Ring as Ring
-
-import Data.Word (Word32)
-import Data.Int (Int32)
-
-import NumericPrelude.Numeric as NP
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith)
-
-
-
-withSize ::
-   (TypeNum.Positive n) =>
-   (TypeNum.Singleton n -> T p (Serial.Value n a)) ->
-   T p (Serial.Value n a)
-withSize f = f TypeNum.singleton
-
-withSizeRing ::
-   (Ring.C b, TypeNum.Positive n) =>
-   (TypeNum.Singleton n -> b -> T p (Serial.Value n a)) ->
-   T p (Serial.Value n a)
-withSizeRing f =
-   withSize $ \n -> f n $ fromInteger $ TypeNum.integerFromSingleton n
-
-
-constant ::
-   (Marshal.Vector n a, Tuple.ValueOf a ~ Value a, IsConst a,
-    Tuple.VectorValueOf n a ~ Value (Vector n a),
-    IsPrimitive a, SizeOf a ~ asize,
-    TypeNum.Positive (n :*: asize),
-    TypeNum.Positive n) =>
-   Param.T p a -> T p (Serial.Value n a)
-constant x =
-   withSize $ \n -> Sig.constant (Serial.replicate_ n ^<< x)
-
-
-exponential2 ::
-   (Trans.C a, Marshal.Vector n a, Tuple.ValueOf a ~ Value a,
-    Tuple.VectorValueOf n a ~ Value (Vector n a),
-    IsArithmetic a, IsConst a,
-    IsPrimitive a, SizeOf a ~ asize,
-    TypeNum.Positive (n :*: asize),
-    TypeNum.Positive n) =>
-   Param.T p a -> Param.T p a -> T p (Serial.Value n a)
-exponential2 halfLife start = withSizeRing $ \sn n ->
-   Sig.exponentialCore
-      (Serial.replicate_ sn ^<< 0.5 ** (n / halfLife))
-      (liftA2
-         (\h -> Serial.iteratePlain (0.5 ** recip h *))
-         halfLife start)
-
-exponentialBounded2 ::
-   (Trans.C a, Marshal.Vector n a, Tuple.ValueOf a ~ Value a,
-    Tuple.VectorValueOf n a ~ Value (Vector n a),
-    Vector.Real a, IsConst a,
-    IsPrimitive a, SizeOf a ~ as,
-    TypeNum.Positive (n :*: as),
-    TypeNum.Positive n) =>
-   Param.T p a -> Param.T p a -> Param.T p a ->
-   T p (Serial.Value n a)
-exponentialBounded2 bound halfLife start = withSizeRing $ \sn n ->
-   Sig.exponentialBoundedCore
-      (fmap (Serial.replicate_ sn) bound)
-      (Serial.replicate_ sn ^<< 0.5 ** (n / halfLife))
-      (liftA2
-         (\h -> Serial.iteratePlain (0.5 ** recip h *))
-         halfLife start)
-
-
-osciCore ::
-   (Marshal.Vector n t, Tuple.ValueOf t ~ Value t,
-    Tuple.VectorValueOf n t ~ Value (Vector n t),
-    IsPrimitive t, SizeOf t ~ tsize,
-    TypeNum.Positive (n :*: tsize),
-    Vector.Real t, IsFloating t, RealField.C t, IsConst t,
-    TypeNum.Positive n) =>
-   Param.T p t -> Param.T p t -> T p (Serial.Value n t)
-osciCore phase freq = withSizeRing $ \sn n ->
-   Sig.osciCore
-      (liftA2
-         (\f -> Serial.iteratePlain (fraction . (f +)))
-         freq phase)
-      (fmap
-         (\f -> Serial.replicate_ sn (fraction (n * f)))
-         freq)
-
-osci ::
-   (Marshal.Vector n t, Tuple.ValueOf t ~ Value t,
-    Marshal.C c, Tuple.ValueOf c ~ cl,
-    Tuple.VectorValueOf n t ~ Value (Vector n t),
-    IsPrimitive t, SizeOf t ~ tsize,
-    TypeNum.Positive (n :*: tsize),
-    Memory.C cl,
-    Vector.Real t, IsFloating t, RealField.C t, IsConst t,
-    TypeNum.Positive n) =>
-   (forall r. cl -> Serial.Value n t -> CodeGenFunction r y) ->
-   Param.T p c ->
-   Param.T p t -> Param.T p t -> T p y
-osci wave waveParam phase freq =
-   Sig.map wave waveParam $
-   osciCore phase freq
-
-osciSimple ::
-   (Marshal.Vector n t, Tuple.ValueOf t ~ Value t,
-    Tuple.VectorValueOf n t ~ Value (Vector n t),
-    IsPrimitive t, SizeOf t ~ tsize,
-    TypeNum.Positive (n :*: tsize),
-    Vector.Real t, IsFloating t, RealField.C t, IsConst t,
-    TypeNum.Positive n) =>
-   (forall r. Serial.Value n t -> CodeGenFunction r y) ->
-   Param.T p t -> Param.T p t -> T p y
-osciSimple wave =
-   osci (const wave) (return ())
-
-
-rampInf, rampSlope,
- parabolaFadeInInf, parabolaFadeOutInf ::
-   (RealField.C a, Marshal.Vector n a, Tuple.ValueOf a ~ Value a,
-    Tuple.VectorValueOf n a ~ Value (Vector n a),
-    IsPrimitive a, SizeOf a ~ as,
-    TypeNum.Positive (n :*: as),
-    IsArithmetic a, SoV.IntegerConstant a,
-    TypeNum.Positive n) =>
-   Param.T p a -> T p (Serial.Value n a)
-rampSlope slope = withSizeRing $ \sn n ->
-   Sig.rampCore
-      (fmap (\s -> Serial.replicate_ sn (n * s)) slope)
-      (fmap (\s -> Serial.iteratePlain (s +) 0) slope)
-rampInf dur = rampSlope (recip dur)
-
-parabolaFadeInInf dur = withSizeRing $ \sn n ->
-   Sig.parabolaCore
-      (fmap
-         (\dr ->
-            let d = n / dr
-            in  Serial.replicate_ sn (-2*d*d)) dur)
-      (fmap
-         (\dr ->
-            let d = n / dr
-            in  Serial.iteratePlain (subtract $ 2 / dr ^ 2) (d*(2-d)))
-         dur)
-      (fmap
-         (\dr ->
-            Serial.mapPlain (\t -> t*(2-t)) $ Serial.iteratePlain (recip dr +) 0)
-         dur)
-
-parabolaFadeOutInf dur = withSizeRing $ \sn n ->
-   Sig.parabolaCore
-      (fmap
-         (\dr ->
-            let d = n / dr
-            in  Serial.replicate_ sn (-2*d*d)) dur)
-      (fmap
-         (\dr ->
-            let d = n / dr
-            in  Serial.iteratePlain (subtract $ 2 / dr ^ 2) (-d*d))
-         dur)
-      (fmap
-         (\dr ->
-            Serial.mapPlain (\t -> 1-t*t) $ Serial.iteratePlain (recip dr +) 0)
-         dur)
-
-
-{- |
-For the mysterious rate parameter see 'Sig.noise'.
--}
-noise ::
-   (Algebraic.C a, IsFloating a, SoV.IntegerConstant a,
-    TypeNum.Positive n,
-    TypeNum.Positive (n :*: TypeNum.D32),
-    IsPrimitive a, SizeOf a ~ as,
-    TypeNum.Positive (n :*: as),
-    Marshal.Vector n a, Tuple.VectorValueOf n a ~ Value (Vector n a),
-    Tuple.ValueOf a ~ Value a) =>
-   Param.T p Word32 ->
-   Param.T p a ->
-   T p (Serial.Value n a)
-noise seed rate =
-   withSize $ \n ->
-   let m2 = div Rnd.modulus 2
-   in  Sig.map
-          (\r y ->
-             A.mul r
-              =<< flip A.sub (A.fromInteger' $ m2+1)
-              =<< int31tofp y)
-          (Serial.replicate_ n ^<< sqrt (3 * rate) / return (fromInteger m2)) $
-       noiseCore seed
-
-{-
-sitofp is a single instruction on x86
-and thus we use it, since the arguments are below 2^31.
--}
-int31tofp ::
-   (IsFloating a, IsPrimitive a,
-    TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
-   Serial.Value n Word32 -> CodeGenFunction r (Serial.Value n a)
-int31tofp =
-   Serial.mapV $
-   LLVM.inttofp <=<
-   (LLVM.bitcast ::
-       (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
-       Value (Vector n Word32) ->
-       CodeGenFunction r (Value (Vector n Int32)))
-
-noiseCore, noiseCoreAlt ::
-   (TypeNum.Positive n,
-    TypeNum.Positive (n :*: TypeNum.D32)) =>
-   Param.T p Word32 ->
-   T p (Serial.Value n Word32)
-noiseCore seed =
-   fmap Serial.value $
-   Sig.iterate (const Rnd.nextVector)
-      (return ())
-      (Rnd.vectorSeed . (+1) . flip mod (Rnd.modulus-1) ^<< seed)
-
-noiseCoreAlt seed =
-   fmap Serial.value $
-   Sig.iterate (const Rnd.nextVector64)
-      (return ())
-      (Rnd.vectorSeed . (+1) . flip mod (Rnd.modulus-1) ^<< seed)
diff --git a/src/Synthesizer/LLVM/Parameterized/SignalPrivate.hs b/src/Synthesizer/LLVM/Parameterized/SignalPrivate.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Parameterized/SignalPrivate.hs
+++ /dev/null
@@ -1,346 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.Parameterized.SignalPrivate where
-
-import qualified Synthesizer.LLVM.Simple.SignalPrivate as Sig
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Either as Either
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Arithmetic as A
-
-import qualified LLVM.DSL.Parameter as Param
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction)
-
-import Control.Arrow ((&&&))
-import Control.Monad (liftM, liftM2)
-import Control.Applicative (Applicative, pure, (<*>))
-
-import Data.Tuple.Strict (zipPair)
-import Data.Monoid (Monoid, mempty, mappend)
-import Data.Semigroup (Semigroup, (<>))
-
-import qualified Number.Ratio as Ratio
-import qualified Algebra.Field as Field
-import qualified Algebra.Ring as Ring
-import qualified Algebra.Additive as Additive
-
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith)
-
-import qualified Prelude as P
-
-
-{-
-In this attempt we use a Haskell value as parameter supply.
-This is okay, since the Haskell value will be converted to internal parameters
-and then to LLVM values only once.
-We can even have a storable vector as parameter.
-However, this way we cannot easily implement
-the Vanilla signal using Parameterized.Value as element type.
-
-This separation is nice for maximum efficiency,
-but it cannot be utilized by Generic.Signal methods.
-Consider an expression like @iterate ((0.5 ** recip halfLife) *) 1@.
-How shall we know, that the sub-expression @(0.5 ** recip halfLife)@
-needs to be computated only once?
-I do not try to do such optimization, instead I let LLVM do it.
-However, this means that parameter initialization
-will be performed (unnecessarily) at the beginning of every chunk.
-For Generic.Signal method instances
-we will always set the @(p -> paramTuple)@ to 'id'.
-
-Could we drop parameterized signals at all
-and rely entirely on Causal processes?
-Unfortunately 'interpolateConstant' does not fit into the Causal process scheme.
-(... although it would be causal for stretching factor being at least one.
-It would have to maintain the waiting signal as state,
-i.e. the state would grow linearly with time.)
-Consider a signal algorithm, where the LFO frequency is a parameter.
--}
-data T p a =
-   forall context state local ioContext parameters.
-      (Marshal.C parameters, Memory.C context, Memory.C state) =>
-   Cons
-      (forall r c.
-       (Tuple.Phi c) =>
-       context -> local -> state -> MaybeCont.T r c (a, state))
-          -- compute next value
-      (forall r.
-       CodeGenFunction r local)
-          -- allocate temporary variables before a loop
-      (forall r.
-       Tuple.ValueOf parameters ->
-       CodeGenFunction r (context, state))
-          -- allocate initial state
-      (forall r.
-       context -> state ->
-       CodeGenFunction r ())
-          {- cleanup
-          You must make sure to call this
-          whenever you allocated context and state with the 'start' function.
-          You must call it with the latest state returned from the 'next' function.
-          -}
-      (p -> IO (ioContext, parameters))
-          {- initialization from IO monad
-          This will be run within Unsafe.performIO,
-          so no observable In/Out actions please!
-          -}
-      (ioContext -> IO ())
-          -- finalization from IO monad, also run within Unsafe.performIO
-
-
-instance Sig.C (T p) where
-   simpleAlloca next alloca0 start =
-      Cons
-         (\() local -> next local)
-         alloca0
-         (const $ fmap ((,) ()) start)
-         (const $ const $ return ())
-         (const $ return ((), ()))
-         (const $ return ())
-
-   alter f (Cons next0 alloca0 start0 stop0 create delete) =
-      case f (Sig.Core (uncurry next0) return id) of
-         Sig.Core next1 start1 stop1 ->
-            Cons
-               (curry next1)
-               alloca0
-               (withStart start0 start1)
-               (\c -> stop0 c . stop1)
-               create delete
-
-
-withStart ::
-   Monad m =>
-   (startParam -> m (context, state0)) ->
-   (state0 -> m state1) ->
-   startParam -> m (context, state1)
-withStart start act p = do
-   (c,s) <- start p
-   liftM ((,) c) $ act s
-
-combineStart ::
-   Monad m =>
-   (paramA -> m (contextA, stateA)) ->
-   (paramB -> m (contextB, stateB)) ->
-   (paramA, paramB) -> m ((contextA, contextB), (stateA, stateB))
-combineStart startA startB (paramA, paramB) =
-   liftM2 zipPair (startA paramA) (startB paramB)
-
-combineStop ::
-   Monad m =>
-   (contextA -> stateA -> m ()) ->
-   (contextB -> stateB -> m ()) ->
-   (contextA, contextB) -> (stateA, stateB) -> m ()
-combineStop stopA stopB (ca, cb) (sa, sb) =
-   stopA ca sa >> stopB cb sb
-
-combineCreate ::
-   Monad m =>
-   (p -> m (ioContextA, contextA)) ->
-   (p -> m (ioContextB, contextB)) ->
-   p -> m ((ioContextA, ioContextB), (contextA, contextB))
-combineCreate createIOContextA createIOContextB p =
-   liftM2 zipPair (createIOContextA p) (createIOContextB p)
-
-combineDelete ::
-   (Monad m) =>
-   (ca -> m ()) -> (cb -> m ()) -> (ca, cb) -> m ()
-combineDelete deleteIOContextA deleteIOContextB (ca,cb) =
-   deleteIOContextA ca >> deleteIOContextB cb
-
-
-
-simple ::
-   (Marshal.C parameters, Tuple.ValueOf parameters ~ paramTuple,
-    Memory.C context, Memory.C state) =>
-   (forall r c.
-    (Tuple.Phi c) =>
-    context -> state -> MaybeCont.T r c (al, state)) ->
-   (forall r.
-    paramTuple ->
-    CodeGenFunction r (context, state)) ->
-   Param.T p parameters -> T p al
-simple f start param =
-   Param.withValue param $ \getParam valueParam ->
-   Cons
-      (\context () state -> f context state)
-      (return ())
-      (start . valueParam)
-      (const $ const $ return ())
-      (return . (,) () . getParam)
-      (const $ return ())
-
-
-constant :: (Marshal.C a, Tuple.ValueOf a ~ al) => Param.T p a -> T p al
-constant =
-   simple
-      (\pl () -> return (pl, ()))
-      (return . flip (,) ())
-
-
-map ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (forall r. pl -> a -> CodeGenFunction r b) ->
-   Param.T p ph ->
-   T p a -> T p b
-map f param =
-   Sig.map (uncurry f) . zip (constant param)
-
--- for backwards compatibility
-mapSimple ::
-   (forall r. a -> CodeGenFunction r b) ->
-   T p a -> T p b
-mapSimple = Sig.map
-
-
-zipWith ::
-   (Marshal.C ph, Tuple.ValueOf ph ~ pl) =>
-   (forall r. pl -> a -> b -> CodeGenFunction r c) ->
-   Param.T p ph ->
-   T p a -> T p b -> T p c
-zipWith f param as bs =
-   map (uncurry . f) param $ zip as bs
-
-zip :: T p a -> T p b -> T p (a,b)
-zip (Cons nextA allocaA startA stopA createIOContextA deleteIOContextA)
-    (Cons nextB allocaB startB stopB createIOContextB deleteIOContextB) =
-   Cons
-      (\(parameterA, parameterB) (localA, localB) (sa0,sb0) -> do
-         (a,sa1) <-
-            MaybeCont.onFail (stopB parameterB sb0) $
-            nextA parameterA localA sa0
-         (b,sb1) <-
-            MaybeCont.onFail (stopA parameterA sa1) $
-            nextB parameterB localB sb0
-         return ((a,b), (sa1,sb1)))
-      (liftM2 (,) allocaA allocaB)
-      (combineStart startA startB)
-      (combineStop stopA stopB)
-      (combineCreate createIOContextA createIOContextB)
-      (combineDelete deleteIOContextA deleteIOContextB)
-
-{-
-maintained for backwards compatibility
-It is a specialisation of Sig.zipWith.
-However, we cannot define zipWithSimple = Sig.zipWith,
-since Sig.zipWith depends on Applicative.liftA2,
-which depends on zipWithSimple.
--}
-zipWithSimple ::
-   (forall r. a -> b -> CodeGenFunction r c) ->
-   T p a -> T p b -> T p c
-zipWithSimple f as bs =
-   mapSimple (uncurry f) $ zip as bs
-
-
-instance Functor (T p) where
-   fmap f = mapSimple (return . f)
-
-{- |
-ZipList semantics
--}
-instance Applicative (T p) where
-   pure x =
-      simple
-         (\() () -> return (x, ()))
-         (\() -> return ((),()))
-         (return ())
-   (<*>) = zipWithSimple (\f a -> return (f a))
-
-
-instance (A.Additive a) => Additive.C (T p a) where
-   zero = pure A.zero
-   negate = mapSimple A.neg
-   (+) = zipWithSimple A.add
-   (-) = zipWithSimple A.sub
-
-instance (A.PseudoRing a, A.IntegerConstant a) => Ring.C (T p a) where
-   one = pure A.one
-   fromInteger n = pure (A.fromInteger' n)
-   (*) = zipWithSimple A.mul
-
-instance (A.Field a, A.RationalConstant a) => Field.C (T p a) where
-   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
-   (/) = zipWithSimple A.fdiv
-
-
-instance (A.PseudoRing a, A.Real a, A.IntegerConstant a) => P.Num (T p a) where
-   fromInteger n = pure (A.fromInteger' n)
-   negate = mapSimple A.neg
-   (+) = zipWithSimple A.add
-   (-) = zipWithSimple A.sub
-   (*) = zipWithSimple A.mul
-   abs = mapSimple A.abs
-   signum = mapSimple A.signum
-
-instance (A.Field a, A.Real a, A.RationalConstant a) => P.Fractional (T p a) where
-   fromRational x = pure (A.fromRational' x)
-   (/) = zipWithSimple A.fdiv
-
-
-{- |
-For restrictions see 'Sig.append'.
--}
-append :: (Tuple.Phi a, Tuple.Undefined a) => T p a -> T p a -> T p a
-append
-      (Cons nextA allocaA startA stopA createIOContextA deleteIOContextA)
-      (Cons nextB allocaB startB stopB createIOContextB deleteIOContextB) =
-   Cons
-      (\parameterB (localA, localB) ecs0 -> MaybeCont.fromMaybe $ do
-         ecs1 <-
-            Either.run ecs0
-               (\(ca, sa0) ->
-                  MaybeCont.resolve
-                     (nextA ca localA sa0)
-                     (fmap Either.right $ startB parameterB)
-                     (\(a1,sa1) -> return (Either.left (a1, (ca, sa1)))))
-               (return . Either.right)
-
-         Either.run ecs1
-            (\(a1,cs1) ->
-               return (Maybe.just (a1, Either.left cs1)))
-            (\(cb,sb0) ->
-               MaybeCont.toMaybe $
-               fmap (\(b,sb1) -> (b, Either.right (cb,sb1))) $
-               nextB cb localB sb0))
-      (liftM2 (,) allocaA allocaB)
-      (\(parameterA, parameterB) -> do
-         cs <- startA parameterA
-         return (parameterB, Either.left cs))
-      (\ _parameterB s -> Either.run s (uncurry stopA) (uncurry stopB))
-      (combineCreate createIOContextA createIOContextB)
-      (combineDelete deleteIOContextA deleteIOContextB)
-
-instance (Tuple.Phi a, Tuple.Undefined a) => Semigroup (T p a) where
-   (<>) = append
-
-instance (Tuple.Phi a, Tuple.Undefined a) => Monoid (T p a) where
-   mempty = Sig.empty
-   mappend = append
-
-
-iterate ::
-   (Marshal.C c, Tuple.ValueOf c ~ cl,
-    Marshal.C a, Tuple.ValueOf a ~ al) =>
-   (forall r. cl -> al -> CodeGenFunction r al) ->
-   Param.T p c -> Param.T p a -> T p al
-iterate f param initial = simple
-   (\pl al0 -> MaybeCont.lift $ fmap (\al1 -> (al0,al1)) (f pl al0))
-   return
-   (param &&& initial)
-
-malloc :: (LLVM.IsSized a) => T p (LLVM.Value (LLVM.Ptr a))
-malloc =
-   Cons
-      (\ptr () () -> return (ptr, ()))
-      (return ())
-      (const $ fmap (flip (,) ()) $ LLVM.malloc)
-      (\ptr () -> LLVM.free ptr)
-      (const $ return ((), ()))
-      (const $ return ())
diff --git a/src/Synthesizer/LLVM/Plug/Input.hs b/src/Synthesizer/LLVM/Plug/Input.hs
--- a/src/Synthesizer/LLVM/Plug/Input.hs
+++ b/src/Synthesizer/LLVM/Plug/Input.hs
@@ -1,9 +1,7 @@
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE ExistentialQuantification #-}
 {-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE UndecidableInstances #-}
 module Synthesizer.LLVM.Plug.Input (
    T(..),
    Default(..),
@@ -21,16 +19,19 @@
 
 import qualified Synthesizer.LLVM.ConstantPiece as Const
 
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Control as C
 
+import qualified LLVM.ExecutionEngine as EE
 import qualified LLVM.Core as LLVM
 
 import qualified Type.Data.Num.Decimal as TypeNum
+import Type.Data.Num.Decimal ((:*:))
 import Type.Base.Proxy (Proxy)
 
 import qualified Synthesizer.MIDI.PiecewiseConstant.ControllerSet as PCS
@@ -49,14 +50,17 @@
 import qualified Foreign.ForeignPtr as FPtr
 import Foreign.Storable (pokeElemOff)
 
-import Control.Applicative (liftA2)
+import qualified Control.Functor.HT as FuncHT
+import Control.Applicative (liftA2, (<$>))
 
 import qualified Data.Map as Map
-
-import Data.Tuple.Strict (mapFst, mapPair, swap, zipPair)
+import qualified Data.List as List
+import Data.Tuple.Strict (mapFst, zipPair)
 import Data.Word (Word)
 
+import Prelude hiding (map)
 
+
 {-
 This datatype does not provide an early exit option, e.g. by Maybe.T,
 since we warrant that the driver function will always
@@ -69,104 +73,90 @@
       (Marshal.C parameters, Memory.C state) =>
    Cons
       (forall r.
-       Tuple.ValueOf parameters ->
+       MultiValue.T parameters ->
        state -> LLVM.CodeGenFunction r (b, state))
-          -- compute next value
+         -- compute next value
       (forall r.
-       Tuple.ValueOf parameters ->
+       MultiValue.T parameters ->
        LLVM.CodeGenFunction r state)
-          -- initial state
+         -- initial state
       (a -> IO (ioContext, parameters))
-          {- initialization from IO monad
-          This is called once input chunk.
-          This will be run within Unsafe.performIO,
-          so no observable In/Out actions please!
-          -}
+         {- initialization from IO monad
+         This is called once input chunk.
+         This will be run within Unsafe.performIO,
+         so no observable In/Out actions please!
+         -}
       (ioContext -> IO ())
-          {-
-          finalization from IO monad, also run within Unsafe.performIO
-          -}
+         {-
+         finalization from IO monad, also run within Unsafe.performIO
+         -}
 
 
 instance Functor (T a) where
    fmap f (Cons next start create delete) =
       Cons (\p s -> fmap (mapFst f) $ next p s) start create delete
 
+map :: (forall r. a -> LLVM.CodeGenFunction r b) -> T inp a -> T inp b
+map f (Cons next start create delete) =
+   Cons (\p s -> FuncHT.mapFst f =<< next p s) start create delete
 
-class Default a where
-   type Element a :: *
-   deflt :: T a (Element a)
 
-instance (Default a, Default b) => Default (Zip.T a b) where
-   type Element (Zip.T a b) = (Element a, Element b)
-   deflt = split deflt deflt
 
-instance Default SigG.LazySize where
-   type Element SigG.LazySize = ()
-   deflt = lazySize
-
-instance (Storable.C a) => Default (SV.Vector a) where
-   type Element (SV.Vector a) = Tuple.ValueOf a
-   deflt = storableVector
-
-
-{-
-This is intentionally restricted to NonNegW.Int aka StrictTimeShort,
-since chunks must fit into memory.
-If you have good reasons to allow other types,
-see the versioning history for an according hack.
--}
-instance
-   (Storable.C a, Memory.C (Tuple.ValueOf a)) =>
-      Default (EventListBT.T NonNegW.Int a) where
-   type Element (EventListBT.T NonNegW.Int a) = Tuple.ValueOf a
-   deflt = piecewiseConstant
-
+class Default a where
+   type Element a
+   deflt :: T a (Element a)
 
 
 rmap :: (a -> b) -> T b c -> T a c
 rmap f (Cons next start create delete) =
    Cons next start (create . f) delete
 
+fanout :: T a b -> T a c -> T a (b,c)
+fanout f g = rmap (\a -> Zip.Cons a a) $ split f g
 
+
+instance (Default a, Default b) => Default (Zip.T a b) where
+   type Element (Zip.T a b) = (Element a, Element b)
+   deflt = split deflt deflt
+
 split :: T a c -> T b d -> T (Zip.T a b) (c,d)
 split (Cons nextA startA createA deleteA)
       (Cons nextB startB createB deleteB) = Cons
-   (\(parameterA, parameterB) (sa,sb) ->
-      liftA2 zipPair
-         (nextA parameterA sa)
-         (nextB parameterB sb))
-   (\(parameterA, parameterB) ->
-      liftA2 (,)
-         (startA parameterA)
-         (startB parameterB))
+   (MultiValue.uncurry $ \parameterA parameterB (sa,sb) ->
+      liftA2 zipPair (nextA parameterA sa) (nextB parameterB sb))
+   (MultiValue.uncurry $ \parameterA parameterB ->
+      liftA2 (,) (startA parameterA) (startB parameterB))
    (\(Zip.Cons a b) ->
-      liftA2 zipPair
-         (createA a)
-         (createB b))
-   (\(ca,cb) ->
-      deleteA ca >>
-      deleteB cb)
+      liftA2 zipPair (createA a) (createB b))
+   (\(ca,cb) -> deleteA ca >> deleteB cb)
 
-fanout :: T a b -> T a c -> T a (b,c)
-fanout f g = rmap (\a -> Zip.Cons a a) $ split f g
 
+instance Default SigG.LazySize where
+   type Element SigG.LazySize = ()
+   deflt = lazySize
+
 lazySize :: T SigG.LazySize ()
 lazySize = ignore
 
 ignore :: T a ()
 ignore =
    Cons
-      (\ _ _ -> return ((), ()))
+      (\ _ unit -> return ((), unit))
       return
       (\ _a -> return ((), ()))
       (const $ return ())
 
-storableVector ::
-   (Storable.C a, Tuple.ValueOf a ~ value) => T (SV.Vector a) value
+instance (Storable.C a) => Default (SV.Vector a) where
+   type Element (SV.Vector a) = MultiValue.T a
+   deflt = storableVector
+
+storableVector :: (Storable.C a) => T (SV.Vector a) (MultiValue.T a)
 storableVector =
    Cons
-      (\ _ p -> liftA2 (,) (Storable.load p) (Storable.incrementPtr p))
+      (\ _ (MultiValue.Cons p) ->
+         liftA2 (,)
+            (Storable.load p)
+            (MultiValue.Cons <$> Storable.incrementPtr p))
       return
       (\vec ->
          let (fp,ptr,_l) = SVU.unsafeToPointers vec
@@ -174,24 +164,40 @@
       -- keep the foreign ptr alive
       FPtr.touchForeignPtr
 
+
 {-
+This is intentionally restricted to NonNegW.Int aka StrictTimeShort,
+since chunks must fit into memory.
+If you have good reasons to allow other types,
+see the versioning history for an according hack.
+-}
+instance
+   (Marshal.C a, time ~ NonNegW.Int) =>
+      Default (EventListBT.T time a) where
+   type Element (EventListBT.T time a) = MultiValue.T a
+   deflt = piecewiseConstant
+
+{-
 I would like to re-use code from ConstantPiece here.
 Unfortunately, it is based on the LLVM-Maybe-Monad,
 but here we do not accept early exit.
 -}
 piecewiseConstant ::
-   (Storable.C a, Tuple.ValueOf a ~ value, Memory.C value) =>
-   T (EventListBT.T NonNegW.Int a) value
+   (Marshal.C a) => T (EventListBT.T NonNegW.Int a) (MultiValue.T a)
 piecewiseConstant =
    expandConstantPieces $
-   rmap (uncurry Zip.Cons .
-         mapPair
-            (SV.pack .
-               map ((fromIntegral :: Int -> Word) . NonNegW.toNumber),
-             SV.pack) .
-         swap . unzip . EventListBT.toPairList) $
-   fmap (uncurry Const.Cons) $
-   split storableVector storableVector
+   rmap
+      (SV.pack .
+       List.map
+         (\(a,t) -> EE.Stored $ LLVM.Struct
+            (fromIntegral $ NonNegW.toNumber t :: Word, (Marshal.pack a, ()))) .
+       EventListBT.toPairList) $
+   map
+      (\(MultiValue.Cons s) -> do
+         t <- LLVM.extractvalue s TypeNum.d0
+         a <- LLVM.extractvalue s TypeNum.d1
+         Const.Cons t . MultiValue.Cons <$> Memory.decompose a) $
+   storableVector
 
 expandConstantPieces ::
    (Memory.C value) => T events (Const.T value) -> T events value
@@ -204,9 +210,7 @@
                 next param s))
       length2 <- A.dec length1
       return (y1, (Const.Cons length2 y1, s1)))
-   (\param ->
-      fmap ((,) (Const.Cons Tuple.zero Tuple.undef)) $
-      start param)
+   (\param -> (,) (Const.Cons Tuple.zero Tuple.undef) <$> start param)
    create delete
 
 
@@ -215,33 +219,41 @@
 in order to forbid writing to the array.
 -}
 controllerSet ::
-   (TypeNum.Natural n, Storable.C a,
-    LLVM.Storable a, Tuple.ValueOf a ~ LLVM.Value a, LLVM.IsSized a) =>
-   Proxy n -> T (PCS.T Int a) (LLVM.Value (LLVM.Array n a))
+   (Marshal.C a, Marshal.Struct a ~ aStruct, LLVM.IsSized aStruct,
+    TypeNum.Natural n,
+    (n:*:LLVM.SizeOf aStruct) ~ arrSize, TypeNum.Natural arrSize) =>
+   Proxy n -> T (PCS.T Int a) (MultiValue.T (MultiValue.Array n a))
 controllerSet pn =
    controllerSetFromSV pn $
-   split storableVector $ split storableVector storableVector
+   map
+      (\(MultiValue.Cons s) -> do
+         len <- LLVM.extractvalue s TypeNum.d0
+         i   <- LLVM.extractvalue s TypeNum.d1
+         a   <- Memory.decompose =<< LLVM.extractvalue s TypeNum.d2
+         return (len,(i,a))) $
+   storableVector
 
 controllerSetFromSV ::
-   (TypeNum.Natural n,
-    LLVM.Storable a, Tuple.ValueOf a ~ LLVM.Value a, LLVM.IsSized a) =>
+   (Marshal.C a, Marshal.Struct a ~ aStruct, LLVM.IsSized aStruct,
+    TypeNum.Natural n,
+    (n:*:LLVM.SizeOf aStruct) ~ arrSize, TypeNum.Natural arrSize) =>
    Proxy n ->
-   T (Zip.T (SV.Vector Word) (Zip.T (SV.Vector Word) (SV.Vector a)))
-     (LLVM.Value Word, (LLVM.Value Word, LLVM.Value a)) ->
-   T (PCS.T Int a) (LLVM.Value (LLVM.Array n a))
+   T (SV.Vector (EE.Stored (Marshal.Struct (Word,Word,a))))
+     (LLVM.Value Word, (LLVM.Value Word, MultiValue.T a)) ->
+   T (PCS.T Int a) (MultiValue.T (MultiValue.Array n a))
 controllerSetFromSV pn (Cons next start create delete) = Cons
-   (\((arrPtr, _), param) state0 -> do
+   (MultiValue.uncurry $ \(MultiValue.Cons (arrPtr, _)) param state0 -> do
       (length2, s2) <-
          C.whileLoopShared state0
             (\(len0, s0) ->
                (A.cmp LLVM.CmpEQ len0 Tuple.zero,
                 do ((len1, (i,a)), s1) <- next param s0
-                   LLVM.store a =<< LLVM.getElementPtr arrPtr (i, ())
+                   Memory.store a =<< LLVM.getElementPtr arrPtr (i, ())
                    return (len1, s1)))
       length3 <- A.dec length2
-      arr <- LLVM.load =<< LLVM.bitcast arrPtr
+      arr <- Memory.load =<< LLVM.bitcast arrPtr
       return (arr, (length3, s2)))
-   (\((_, initialTime), param) -> do
+   (MultiValue.uncurry $ \(MultiValue.Cons (_, initialTime)) param -> do
       state <- start param
       return (initialTime, state))
 
@@ -250,14 +262,14 @@
          (\initialTime bt -> do
             (context, param) <-
                create
-                  (uncurry Zip.Cons .
-                   mapPair
-                     (SV.pack,
-                      uncurry Zip.Cons . mapPair (SV.pack, SV.pack). unzip) .
-                   unzip .
-                   map (\((i,a),len) ->
-                      (fromIntegral len :: Word,
-                       (fromIntegral i :: Word, a))) .
+                  (SV.pack .
+                   List.map
+                     (\((i,a),len) ->
+                        EE.Stored $
+                        Marshal.pack
+                           (fromIntegral len :: Word,
+                            fromIntegral i :: Word,
+                            a)) .
                    EventListBT.toPairList $
                    bt)
 
@@ -267,11 +279,12 @@
             flip mapM_ (Map.toList $ PCS.initial pcs) $ \(i,a) ->
                if i >= n
                  then error "Plug.Input.controllerSet: array too small"
-                 else pokeElemOff arr i a
+                 else pokeElemOff arr i $ EE.Stored $ Marshal.pack a
 
             return
                ((arr, context),
-                ((LLVM.fromPtr arr, fromIntegral initialTime :: Word), param)))
+                ((EE.castFromStoredPtr arr, fromIntegral initialTime :: Word),
+                  param)))
             {-
             It would be more elegant,
             if we could pass Arrays around just like Vectors.
diff --git a/src/Synthesizer/LLVM/Plug/Output.hs b/src/Synthesizer/LLVM/Plug/Output.hs
--- a/src/Synthesizer/LLVM/Plug/Output.hs
+++ b/src/Synthesizer/LLVM/Plug/Output.hs
@@ -1,9 +1,6 @@
-{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE ExistentialQuantification #-}
 {-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE UndecidableInstances #-}
 module Synthesizer.LLVM.Plug.Output (
    T(..),
    Default(..),
@@ -13,14 +10,14 @@
 
 import qualified Synthesizer.Zip as Zip
 
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Tuple as Tuple
 
 import qualified LLVM.Core as LLVM
 
-import Control.Monad (liftM2)
+import Control.Applicative (liftA2)
 
 import qualified Synthesizer.LLVM.Storable.Vector as SVU
 import qualified Data.StorableVector as SV
@@ -30,76 +27,59 @@
 
 import Data.Tuple.Strict (zipPair)
 
-import NumericPrelude.Numeric
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith, take, takeWhile)
 
-
 data T a b =
    forall state ioContext parameters.
       (Marshal.C parameters, Memory.C state) =>
    Cons
       (forall r.
-       Tuple.ValueOf parameters ->
-       a -> state -> LLVM.CodeGenFunction r state)
-          -- compute next value
-      (forall r.
-       Tuple.ValueOf parameters ->
-       LLVM.CodeGenFunction r state)
-          -- initial state
+       MultiValue.T parameters -> a -> state -> LLVM.CodeGenFunction r state)
+         -- compute next value
+      (forall r. MultiValue.T parameters -> LLVM.CodeGenFunction r state)
+         -- initial state
       (Int -> IO (ioContext, parameters))
-          {- initialization from IO monad
-          This is called once per output chunk
-          with the number of input samples.
-          This number is also the maximum possible number of output samples.
-          This will be run within Unsafe.performIO,
-          so no observable In/Out actions please!
-          -}
+         {- initialization from IO monad
+         This is called once per output chunk
+         with the number of input samples.
+         This number is also the maximum possible number of output samples.
+         This will be run within Unsafe.performIO,
+         so no observable In/Out actions please!
+         -}
       (Int -> ioContext -> IO b)
-          {-
-          finalization from IO monad, also run within Unsafe.performIO
-          The integer argument is the actually produced size of data.
-          We must clip the allocated output vectors accordingly.
-          -}
+         {-
+         finalization from IO monad, also run within Unsafe.performIO
+         The integer argument is the actually produced size of data.
+         We must clip the allocated output vectors accordingly.
+         -}
 
 
 class Default b where
-   type Element b :: *
+   type Element b
    deflt :: T (Element b) b
 
+
 instance (Default c, Default d) => Default (Zip.T c d) where
    type Element (Zip.T c d) = (Element c, Element d)
    deflt = split deflt deflt
 
-instance (Storable.C a) => Default (SV.Vector a) where
-   type Element (SV.Vector a) = Tuple.ValueOf a
-   deflt = storableVector
-
-
 split :: T a c -> T b d -> T (a,b) (Zip.T c d)
 split (Cons nextA startA createA deleteA)
       (Cons nextB startB createB deleteB) = Cons
-   (\(parameterA, parameterB) (a,b) (sa,sb) ->
-      liftM2 (,)
-         (nextA parameterA a sa)
-         (nextB parameterB b sb))
-   (\(parameterA, parameterB) ->
-      liftM2 (,)
-         (startA parameterA)
-         (startB parameterB))
-   (\len ->
-      liftM2 zipPair
-         (createA len)
-         (createB len))
-   (\len (ca,cb) ->
-      liftM2 Zip.Cons
-         (deleteA len ca)
-         (deleteB len cb))
+   (MultiValue.uncurry $ \parameterA parameterB (a,b) (sa,sb) ->
+      liftA2 (,) (nextA parameterA a sa) (nextB parameterB b sb))
+   (MultiValue.uncurry $ \parameterA parameterB ->
+      liftA2 (,) (startA parameterA) (startB parameterB))
+   (\len -> liftA2 zipPair (createA len) (createB len))
+   (\len (ca,cb) -> liftA2 Zip.Cons (deleteA len ca) (deleteB len cb))
 
 
-storableVector ::
-   (Storable.C a, Tuple.ValueOf a ~ value) => T value (SV.Vector a)
+instance (Storable.C a) => Default (SV.Vector a) where
+   type Element (SV.Vector a) = MultiValue.T a
+   deflt = storableVector
+
+storableVector :: (Storable.C a) => T (MultiValue.T a) (SV.Vector a)
 storableVector = Cons
-   (const Storable.storeNext)
+   (\ _param -> MultiValue.liftM . Storable.storeNext)
    return
    (\len -> do
       vec <- SVB.create len (const $ return ())
diff --git a/src/Synthesizer/LLVM/Private.hs b/src/Synthesizer/LLVM/Private.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Private.hs
@@ -0,0 +1,26 @@
+module Synthesizer.LLVM.Private where
+
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Multi.Value as MultiValue
+
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import Control.Applicative (liftA2)
+
+
+unbool :: MultiValue.T Bool -> LLVM.Value Bool
+unbool (MultiValue.Cons b) = b
+
+noLocalPtr :: f -> (LLVM.Value (LLVM.Ptr (LLVM.Struct ())) -> f)
+noLocalPtr = const
+
+getPairPtrs ::
+   LLVM.Value (LLVM.Ptr (LLVM.Struct (a, (b, ())))) ->
+   MaybeCont.T r c (LLVM.Value (LLVM.Ptr a), LLVM.Value (LLVM.Ptr b))
+getPairPtrs ptr =
+   MaybeCont.lift $
+   liftA2 (,)
+      (LLVM.getElementPtr0 ptr (TypeNum.d0, ()))
+      (LLVM.getElementPtr0 ptr (TypeNum.d1, ()))
diff --git a/src/Synthesizer/LLVM/Server/CausalPacked/Common.hs b/src/Synthesizer/LLVM/Server/CausalPacked/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Server/CausalPacked/Common.hs
@@ -0,0 +1,37 @@
+module Synthesizer.LLVM.Server.CausalPacked.Common where
+
+import Synthesizer.LLVM.Server.Common (SampleRate(SampleRate), Real)
+
+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
+
+import qualified Data.EventList.Relative.TimeTime as EventListTT
+
+import qualified Numeric.NonNegative.Class as NonNeg
+
+import Prelude hiding (Real)
+
+
+-- ToDo: might be moved to event-list package
+chopEvents ::
+   (NonNeg.C time, Num time) =>
+   time ->
+   EventListTT.T time body ->
+   [EventListTT.T time body]
+chopEvents chunkSize =
+   let go evs =
+          -- splitBeforeTime?
+          let (chunk,rest) = EventListTT.splitAtTime chunkSize evs
+          in  if EventListTT.duration chunk == 0
+                then []
+                else chunk : go rest
+   in  go
+
+
+transposeModulation ::
+   (Functor stream) =>
+   SampleRate Real ->
+   Real ->
+   stream (BM.T Real) ->
+   stream (BM.T Real)
+transposeModulation (SampleRate sampleRate) freq =
+   fmap (BM.shift (freq/sampleRate))
diff --git a/src/Synthesizer/LLVM/Server/CausalPacked/Instrument.hs b/src/Synthesizer/LLVM/Server/CausalPacked/Instrument.hs
--- a/src/Synthesizer/LLVM/Server/CausalPacked/Instrument.hs
+++ b/src/Synthesizer/LLVM/Server/CausalPacked/Instrument.hs
@@ -32,12 +32,12 @@
    frequencyControl, zipEnvelope,
    ) where
 
-import qualified Synthesizer.LLVM.Server.Parameter as ParamS
 import Synthesizer.LLVM.Server.Packed.Instrument (stereoNoise)
+import Synthesizer.LLVM.Server.CausalPacked.Common (transposeModulation)
 import Synthesizer.LLVM.Server.CommonPacked
-import Synthesizer.LLVM.Server.Common hiding (Instrument)
-import Synthesizer.LLVM.Server.Parameter
-         (Number(Number), VectorTime(VectorTime), Signal(Signal))
+import Synthesizer.LLVM.Server.Common hiding
+         (Instrument, Frequency, Time, Control, transposeModulation)
+import Synthesizer.LLVM.Server.Common (Arg(Frequency, Time))
 
 import qualified Synthesizer.LLVM.Server.SampledSound as Sample
 import qualified Synthesizer.LLVM.Storable.Process as PSt
@@ -45,31 +45,31 @@
 import qualified Synthesizer.CausalIO.Gate as Gate
 import qualified Synthesizer.CausalIO.Process as PIO
 
-import Synthesizer.LLVM.CausalParameterized.Process (($<))
-import Synthesizer.LLVM.CausalParameterized.Functional (($&), (&|&))
 import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
 import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
 import qualified Synthesizer.LLVM.Filter.Moog as Moog
-import qualified Synthesizer.LLVM.Generator.Exponential2 as Exp
+import qualified Synthesizer.LLVM.Causal.Exponential2 as Exp
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 import qualified Synthesizer.LLVM.Frame as Frame
 import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.CausalParameterized.Helix as Helix
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessValue as CausalPV
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.Helix as Helix
+import qualified Synthesizer.LLVM.Causal.Functional as F
+import qualified Synthesizer.LLVM.Causal.ControlledPacked as CtrlPS
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Interpolation as Interpolation
 import qualified Synthesizer.LLVM.Wave as WaveL
-import qualified Synthesizer.LLVM.Simple.Value as Value
-import Synthesizer.LLVM.Simple.Value ((%>), (%<=))
+import Synthesizer.LLVM.Causal.Functional (($&), (&|&))
+import Synthesizer.LLVM.Causal.Process (($<), ($>), ($<#))
 
 import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
 import qualified Synthesizer.LLVM.MIDI as MIDIL
 import qualified Synthesizer.PiecewiseConstant.Signal as PC
+import qualified Synthesizer.Causal.Class as CausalClass
 import qualified Synthesizer.Generic.Cut as CutG
 import qualified Synthesizer.Zip as Zip
 import qualified Data.EventList.Relative.BodyTime as EventListBT
@@ -78,24 +78,31 @@
 import qualified Data.StorableVector.Lazy as SVL
 import qualified Data.StorableVector as SV
 
-import qualified LLVM.DSL.Parameter as Param
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp, (<=*), (>*))
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Core as LLVM
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
+import qualified Control.Applicative.HT as App
 import qualified Control.Monad.HT as M
 import Control.Arrow (Arrow, arr, first, second, (&&&), (<<^), (^<<))
 import Control.Category (id, (.))
-import Control.Monad (liftM2, liftM3, liftM4, (<=<))
-import Control.Applicative (pure, liftA2, liftA3)
+import Control.Applicative (liftA2, liftA3, (<$>))
+import Control.Functor.HT (unzip)
 
 import qualified Data.Traversable as Trav
+import Data.Semigroup ((<>))
 import Data.Monoid (mappend)
+import Data.Tuple.HT (mapPair)
 
 import qualified Number.DimensionTerm as DN
 
 import NumericPrelude.Numeric
-import NumericPrelude.Base hiding (id, (.))
+import NumericPrelude.Base hiding (id, unzip, (.))
 
 
 type Instrument a sig = SampleRate a -> MIO.Instrument a sig
@@ -113,16 +120,24 @@
 type PIOId a = PIO.T a a
 
 
+
+frequencyFromBendModulationPacked ::
+   Exp Real ->
+   F.T inp (MultiValue.T (BM.T Real)) ->
+   F.T inp VectorValue
+frequencyFromBendModulationPacked speed fm =
+   MIDIL.frequencyFromBendModulationPacked speed $& (BM.unMultiValue <$> fm)
+
 stereoFrequenciesFromDetuneBendModulation ::
-   Param p Real ->
-   (FuncP p inp (LLVM.Value Real),
-    FuncP p inp (BM.T (LLVM.Value Real))) ->
-   FuncP p inp (Stereo.T VectorValue)
+   Exp Real ->
+   (F.T inp (MultiValue.T Real),
+    F.T inp (MultiValue.T (BM.T Real))) ->
+   F.T inp (Stereo.T VectorValue)
 stereoFrequenciesFromDetuneBendModulation speed (detune, freq) =
-   CausalP.envelopeStereo $&
-      (MIDIL.frequencyFromBendModulationPacked speed $& freq)
+   Causal.envelopeStereo $&
+      frequencyFromBendModulationPacked speed freq
       &|&
-      (CausalP.mapSimple (Trav.mapM Serial.upsample) $&
+      (Causal.map (fmap Serial.upsample) $&
        liftA2 Stereo.cons (one + detune) (one - detune))
 
 
@@ -146,12 +161,9 @@
 frequencyControl sr =
    fmap (flip DN.divToScalar $ frequencyFromSampleRate sr)
 
-takeThreshold ::
-   Param.T p Real ->
-   CausalP.T p VectorValue VectorValue
-takeThreshold =
-   CausalPV.takeWhile
-      (\threshold y -> threshold %<= Value.lift1 Serial.subsample y)
+takeThreshold :: Exp Real -> Causal.T VectorValue VectorValue
+takeThreshold threshold =
+   Causal.takeWhile (\y -> threshold <=* Serial.subsample y)
 
 
 type EnvelopeControl =
@@ -188,16 +200,16 @@
 ping :: IO (Instrument Real Chunk)
 ping =
    fmap (\proc sampleRate vel freq ->
-      proc (sampleRate, (vel,freq))
+      proc sampleRate vel freq
       .
       Gate.toStorableVector) $
-   CausalP.processIO $
-      let vel = number fst
-          freq = frequency snd
-      in  CausalP.fromSignal $
-          SigP.envelope
-             (SigPS.exponential2 (timeConst 0.2) (fmap amplitudeFromVelocity vel)) $
-          SigPS.osciSimple WaveL.saw zero freq
+   CausalRender.run $
+   wrapped $ \(Number vel) (Frequency freq) ->
+   constant time 0.2 $ \halfLife _sr ->
+      Causal.fromSignal $
+         SigPS.exponential2 halfLife (amplitudeFromVelocity vel)
+         *
+         SigPS.osci WaveL.saw zero freq
 
 
 pingReleaseEnvelope ::
@@ -205,38 +217,40 @@
        SampleRate Real -> Real ->
        PIO.T MIO.GateChunk Chunk)
 pingReleaseEnvelope =
-   liftM2
+   liftA2
       (\sustain release dec rel sr vel ->
          PSt.continuePacked
-            (sustain (sr,(dec,vel))
+            (sustain sr dec vel
              .
              Gate.toChunkySize)
             (\y ->
-               release (sr,(rel,y))
+               release sr rel y
                .
                Gate.allToChunkySize))
-      (CausalP.processIO $
-       ParamS.withTuple2 $ \(VectorTime decay, Number vel) ->
-         CausalP.fromSignal $
-         SigPS.exponential2 decay (fmap amplitudeFromVelocity vel))
-      (CausalP.processIO $
-       ParamS.withTuple2 $ \(ParamS.Time release, Number level) ->
-         CausalP.take (fmap round (vectorTime (const 1)))
+      (CausalRender.run $
+       wrapped $ \(Time decay) (Number vel) (SampleRate _sr) ->
+         Causal.fromSignal $
+         SigPS.exponential2
+            -- FixMe: is division vectorSize correct?
+            (decay / fromIntegral vectorSize) (amplitudeFromVelocity vel))
+      (CausalRender.run $
+       wrapped $ \(Time releaseHL) (Number level) ->
+       constant time 1 $ \releaseTime _sr ->
+         Causal.take
+            (Expr.roundToIntFast $ releaseTime / fromIntegral vectorSize)
          .
-         CausalP.fromSignal (SigPS.exponential2 release level))
+         Causal.fromSignal (SigPS.exponential2 releaseHL level))
 
 pingRelease :: IO (Real -> Real -> Instrument Real Chunk)
 pingRelease =
-   liftM2
+   liftA2
       (\osci envelope dec rel sr vel freq ->
-         osci (sr, freq)
+         osci sr freq
          .
          envelope dec rel sr vel)
-      (CausalP.processIO $
-         let freq = frequency id
-         in  CausalP.envelope
-             .
-             CausalP.feedFst (SigPS.osciSimple WaveL.saw zero freq))
+      (CausalRender.run $
+       wrapped $ \(Frequency freq) (SampleRate _sr) ->
+         Causal.envelope $> SigPS.osci WaveL.saw zero freq)
       pingReleaseEnvelope
 
 
@@ -245,27 +259,27 @@
    IO (SampleRate Real -> Real ->
        PIO.T EnvelopeControl Chunk)
 pingControlledEnvelope threshold =
-   liftM2
+   liftA2
       (\sustain release sr vel ->
          PSt.continuePacked
-            (sustain (sr,vel)
+            (sustain sr vel
              .
              Gate.shorten
              .
              Zip.arrowSecond (arr (halfLifeControl sr . Zip.first)))
             (\y ->
-             release (sr,y)
+             release sr y
              <<^
              halfLifeControl sr . Zip.second . Zip.second))
-      (CausalP.processIO $
-         let vel = number id
-         in  Exp.causalPackedP
-                (fmap amplitudeFromVelocity vel))
-      (CausalP.processIO $
-         let level = number id
-             expo = Exp.causalPackedP level
+      (CausalRender.run $
+       wrapped $ \(Number vel) (SampleRate _sr) ->
+         Exp.causalPacked (amplitudeFromVelocity vel)
+            <<^ Exp.unMultiValueParameterPacked)
+      (CausalRender.run $
+       wrapped $ \(Number level) (SampleRate _sr) ->
+         let expo = Exp.causalPacked level <<^ Exp.unMultiValueParameterPacked
          in  case threshold of
-                Just y -> takeThreshold (pure y) . expo
+                Just y -> takeThreshold (Expr.cons y) . expo
                 Nothing -> expo)
 
 
@@ -282,7 +296,7 @@
 pingStereoReleaseFM =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, ())
+         osc sr
          .
          Zip.arrowSecond
             (Zip.arrowSplit
@@ -294,28 +308,33 @@
                    arr $ halfLifeControl sr)))
          .
          zipEnvelope (env sr vel))
-      (CausalP.processIO
-         (CausalP.envelopeStereo
+      (CausalRender.run $
+       constant frequency 10 $ \speed _sr ->
+         (arr Stereo.multiValue
           .
+          Causal.envelopeStereo
+          .
           second
              (F.withArgs $ \((shape0,shapeDecay),((phase,phaseDecay),fm)) ->
-              let shape = CausalP.mapSimple Serial.upsample $& shape0
+              let shape = Causal.map Serial.upsample $& shape0
                   shapeCtrl =
                      1/pi + (shape-1/pi) *
-                        (Exp.causalPackedP (1::Param.T p Real) $& shapeDecay)
-                  freqs =
-                     stereoFrequenciesFromDetuneBendModulation
-                        (frequencyConst 10) fm
+                        (Exp.causalPacked 1
+                              <<^ Exp.unMultiValueParameterPacked
+                           $& shapeDecay)
+                  freqs = stereoFrequenciesFromDetuneBendModulation speed fm
                   expo =
-                     (CausalP.mapSimple Serial.upsample $& phase) *
-                     (Exp.causalPackedP (1::Param.T p Real) $& phaseDecay)
+                     (Causal.map Serial.upsample $& phase) *
+                     (Exp.causalPacked 1 <<^ Exp.unMultiValueParameterPacked
+                        $& phaseDecay)
                   osci ::
-                     CausalP.T p
+                     Causal.T
                         (VectorValue, (VectorValue, VectorValue)) VectorValue
                   osci = CausalPS.shapeModOsci WaveL.rationalApproxSine1
               in  liftA2 Stereo.cons
                      (osci $&  shapeCtrl &|& (expo &|& fmap Stereo.left freqs))
-                     (osci $&  shapeCtrl &|& (negate expo &|& fmap Stereo.right freqs)))))
+                     (osci $&  shapeCtrl &|&
+                                 (negate expo &|& fmap Stereo.right freqs)))))
       (pingControlledEnvelope (Just 0.01))
 
 
@@ -331,7 +350,7 @@
 filterSawStereoFM =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, ())
+         osc sr
          .
          Zip.arrowSecond
             (Zip.arrowSplit
@@ -342,33 +361,37 @@
                   arr $ transposeModulation sr freq))
          .
          zipEnvelope (env sr vel))
-      (CausalP.processIO
-         (CausalP.envelopeStereo
+      (CausalRender.run $
+       constant frequency 10 $ \speed ->
+       constant frequency 100 $ \lowerFreq _sr ->
+         (arr Stereo.multiValue
           .
+          Causal.envelopeStereo
+          .
           second
              (F.withArgs $ \((cutoff,cutoffDecay),fm) ->
-              let freqs =
-                     stereoFrequenciesFromDetuneBendModulation
-                        (frequencyConst 10) fm
+              let freqs = stereoFrequenciesFromDetuneBendModulation speed fm
                   {- bound control in order to avoid too low resonant frequency,
                      which makes the filter instable -}
                   expo =
-                     takeThreshold (frequencyConst 100) $&
-                     (CausalP.mapSimple Serial.upsample $& cutoff) *
-                     (Exp.causalPackedP (1::Param.T p Real) $& cutoffDecay)
-              in  CausalP.stereoFromMonoControlled
+                     takeThreshold lowerFreq $&
+                     (Causal.map Serial.upsample $& cutoff) *
+                     (Exp.causalPacked 1 <<^ Exp.unMultiValueParameterPacked
+                        $& cutoffDecay)
+              in  Causal.stereoFromMonoControlled
                      (UniFilter.lowpass ^<< CtrlPS.process)
                   $&
-                  (CausalP.quantizeLift (100 / fromIntegral vectorSize :: Param.T p Real)
-                      (CausalP.mapSimple
-                          (UniFilter.parameter (LLVM.valueOf 10)
-                           <=<
+                  ((Causal.quantizeLift
+                     (Causal.map
+                          (UniFilter.parameter 10
+                           .
                            Serial.subsample))
+                     $<# (100 / fromIntegral vectorSize :: Real))
                    $&
                    expo)
                   &|&
-                  (CausalP.stereoFromMono
-                     (CausalPS.osciSimple WaveL.saw $< zero) $&
+                  (Causal.stereoFromMono
+                     (CausalPS.osci WaveL.saw $< zero) $&
                      freqs))))
       (pingControlledEnvelope (Just 0.01))
 
@@ -383,38 +406,94 @@
 tineStereoFM =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, vel)
+         osc sr vel
          .
          (Zip.arrowSecond $ Zip.arrowSecond $
           Zip.arrowSecond $
             arr $ transposeModulation sr freq)
          .
          zipEnvelope (env sr vel))
-      (CausalP.processIO
-         (CausalP.envelopeStereo
+      (CausalRender.run $
+       wrapped $ \(Number vel) ->
+       constant frequency 5 $ \speed ->
+       constant time 1 $ \halfLife _sr ->
+         (arr Stereo.multiValue
           .
+          Causal.envelopeStereo
+          .
           second
              (F.withArgs $ \((index0,depth0), fm) ->
-              let vel = number id
-                  freqs =
-                     stereoFrequenciesFromDetuneBendModulation
-                        (frequencyConst 5) fm
-                  index = CausalP.mapSimple Serial.upsample $& index0
-                  depth = CausalP.mapSimple Serial.upsample $& depth0
-                  expo =
-                     F.fromSignal $
-                     SigPS.exponential2 (timeConst 1) (1 + vel)
-                  osci freq =
-                     CausalPS.osciSimple WaveL.approxSine2 $&
-                        expo * depth *
-                           (CausalPS.osciSimple WaveL.approxSine2
-                            $& zero &|& index*freq)
-                        &|&
-                        freq
-              in  Stereo.liftApplicative osci freqs)))
+              let freqs = stereoFrequenciesFromDetuneBendModulation speed fm
+                  index = Causal.map Serial.upsample $& index0
+                  depth = Causal.map Serial.upsample $& depth0
+                  expo = F.fromSignal $ SigPS.exponential2 halfLife (1 + vel)
+                  osci indexDepth freq =
+                     case unzip indexDepth of
+                        (index1,depth1) ->
+                           CausalPS.osci WaveL.approxSine2 $&
+                              expo * depth1 *
+                                 (CausalPS.osci WaveL.approxSine2
+                                  $& zero &|& index1*freq)
+                              &|&
+                              freq
+              in  stereoFromMonoControlled osci (index&|&depth) freqs)))
       (pingControlledEnvelope (Just 0.01))
 
+{- |
+'Stereo.liftApplicative' specialised to 'T'.
 
+Should be moved to Functional utility module.
+(Functional module itself would cause cyclic dependency.)
+-}
+stereoFromMonoControlled,
+      _stereoFromMonoControlledArgs,
+      _stereoFromMonoControlledGrounded,
+      _stereoFromMonoControlledGuided,
+      _stereoFromMonoControlledPrepared,
+      _stereoFromMonoControlledPrepared2 ::
+   (Tuple.Phi a, Tuple.Phi b, Tuple.Phi c) =>
+   (Tuple.Undefined a, Tuple.Undefined b, Tuple.Undefined c) =>
+   (forall inp0. F.T inp0 c -> F.T inp0 a -> F.T inp0 b) ->
+   F.T inp c -> F.T inp (Stereo.T a) -> F.T inp (Stereo.T b)
+stereoFromMonoControlled proc ctrl stereo =
+   Causal.stereoFromMonoControlled
+      (F.compile $ uncurry proc $ unzip $ F.lift id)
+   $&
+   ctrl &|& stereo
+
+_stereoFromMonoControlledArgs proc ctrl stereo =
+   Causal.stereoFromMonoControlled
+      (F.withArgs (uncurry proc) <<^ mapPair (F.AnyArg, F.AnyArg))
+   $&
+   ctrl &|& stereo
+
+_stereoFromMonoControlledGrounded proc ctrl stereo =
+   Causal.stereoFromMonoControlled
+      (F.withGroundArgs $ \(F.Ground c, F.Ground s) -> proc c s)
+   $&
+   ctrl &|& stereo
+
+_stereoFromMonoControlledGuided proc ctrl stereo =
+   Causal.stereoFromMonoControlled
+      (F.withGuidedArgs (F.atom, F.atom) (uncurry proc))
+   $&
+   ctrl &|& stereo
+
+_stereoFromMonoControlledPrepared proc ctrl stereo =
+   Causal.stereoFromMonoControlled
+      (F.withPreparedArgs (F.pairArgs F.atomArg F.atomArg) (uncurry proc))
+   $&
+   ctrl &|& stereo
+
+_stereoFromMonoControlledPrepared2 proc ctrl stereo =
+   Causal.stereoFromMonoControlled
+      (F.withPreparedArgs2 F.atomArg F.atomArg proc)
+   $&
+   ctrl &|& stereo
+
+
+type RealValue = MultiValue.T Real
+
 bellNoiseStereoFM ::
    IO (SampleRate Real -> Real -> Real ->
        PIO.T
@@ -426,7 +505,7 @@
 bellNoiseStereoFM =
    liftA3
       (\osc env envInf sr vel freq ->
-         osc (sr, ())
+         osc sr
          .
          (Zip.arrowSecond $ Zip.arrowSecond $
           Zip.arrowSecond $
@@ -450,36 +529,40 @@
                       (envInf sr (vel*4)
                        .
                        Zip.arrowSecond (shortenTimes 7)))))
-      (CausalP.processIO
+      (CausalRender.run $
+       constant noiseReference 20000 $ \noiseRef ->
+       constant frequency 5 $ \speed _sr ->
          (F.withArgs $ \((env1,(env4,env7)),((noiseAmp0,noiseReson),fm)) ->
-          let noiseAmp = CausalP.mapSimple Serial.upsample $& noiseAmp0
+          let noiseAmp = Causal.map Serial.upsample $& noiseAmp0
+              noiseParam ::
+                  Causal.T
+                     (RealValue, RealValue)
+                     (Moog.Parameter TypeNum.D8 RealValue)
               noiseParam =
-                 CausalP.quantizeLift
-                    (100 / fromIntegral vectorSize :: Param.T p Real)
-                    (CausalP.zipWithSimple (Moog.parameter TypeNum.d8))
-              noise =
-                 F.fromSignal (SigPS.noise 12 (noiseReference 20000))
-              freqs =
-                 stereoFrequenciesFromDetuneBendModulation
-                    (frequencyConst 5) fm
+                 Causal.quantizeLift
+                       (Causal.zipWith (Moog.parameter TypeNum.d8))
+                    $<# (100 / fromIntegral vectorSize :: Real)
+              noise = F.fromSignal (SigPS.noise 12 noiseRef)
+              freqs = stereoFrequenciesFromDetuneBendModulation speed fm
               osci amp env n =
                  CausalPS.amplifyStereo amp $&
-                 CausalP.envelopeStereo $&
+                 Causal.envelopeStereo $&
                  env &|&
-                 (CausalP.stereoFromMono
-                    (CausalPS.osciSimple WaveL.approxSine4 $< zero)
+                 (Causal.stereoFromMono
+                    (CausalPS.osci WaveL.approxSine4 $< zero)
                   $&
                   CausalPS.amplifyStereo n
                   $&
                   freqs)
-          in  (CausalP.envelopeStereo $&
+          in Stereo.multiValue <$>
+              (Causal.envelopeStereo $&
                  (noiseAmp * env1)
                  &|&
                  Stereo.liftApplicative
                     (\freq ->
                        CtrlPS.process $&
                           (noiseParam $& noiseReson &|&
-                           (CausalP.mapSimple Serial.subsample $& freq))
+                           (Causal.map Serial.subsample $& freq))
                           &|&
                           noise)
                     freqs)
@@ -495,55 +578,54 @@
    IO (SampleRate Real -> Real ->
        PIO.T EnvelopeControl Chunk)
 stringControlledEnvelope =
-   liftM3
+   liftA3
       (\attack sustain release sr vel ->
          let amp = amplitudeFromVelocity vel
          in  PSt.continuePacked
-                (mappend
-                    (attack (sr,amp))
-                    {- we could also feed the sustain process
-                       with a signal with sample type () -}
-                    (sustain (sr,amp))
+                ((attack sr amp <>
+                  {- we could also feed the sustain process
+                     with a signal with sample type () -}
+                  sustain sr amp)
                  .
                  Gate.shorten
                  .
                  Zip.arrowSecond (arr (halfLifeControl sr . Zip.first)))
                 (\y ->
-                 release (sr,y)
+                 release sr y
                  <<^
                  halfLifeControl sr . Zip.second . Zip.second))
-      (CausalP.processIO $
-         let amp = number id
-         in  CausalP.fromSignal (SigPS.constant amp)
+      (CausalRender.run $
+       wrapped $ \(Number amp) (SampleRate _sr) ->
+             Causal.fromSignal (SigPS.constant amp)
              -
-             takeThreshold (1e-4 :: Param.T p Real)
+             takeThreshold 1e-4
              .
-             Exp.causalPackedP amp)
-      (CausalP.processIO $
-         let amp = number id
-         in  CausalP.fromSignal (SigPS.constant amp))
-      (CausalP.processIO $
-         let level = number id
-         in  takeThreshold (0.01 :: Param.T p Real)
+             Exp.causalPacked amp <<^ Exp.unMultiValueParameterPacked)
+      (CausalRender.run $
+       wrapped $ \(Number amp) (SampleRate _sr) ->
+             Causal.fromSignal (SigPS.constant amp))
+      (CausalRender.run $
+       wrapped $ \(Number level) (SampleRate _sr) ->
+             takeThreshold 0.01
              .
-             Exp.causalPackedP level)
+             Exp.causalPacked level <<^ Exp.unMultiValueParameterPacked)
 
 
 windCore ::
-   F.T (SampleRate Real, p) a (LLVM.Value Real) ->
-   F.T (SampleRate Real, p) a (BM.T (LLVM.Value Real)) ->
-   F.T (SampleRate Real, p) a (Stereo.T VectorValue)
+   F.T a (MultiValue.T Real) ->
+   F.T a (MultiValue.T (BM.T Real)) ->
+   SampleRate (Exp Real) ->
+   F.T a (Stereo.T VectorValue)
 windCore reson fm =
+   constant frequency 0.2 $ \speed sr ->
    let modu =
-          CausalP.mapSimple Serial.subsample $&
+          Causal.map Serial.subsample $&
           (fmap (`asTypeOf` (undefined :: VectorValue)) $
-           (MIDIL.frequencyFromBendModulationPacked
-              (frequencyConst 0.2) $& fm))
-   in  CausalP.stereoFromMonoControlled CtrlPS.process $&
-          (CausalP.zipWithSimple (Moog.parameter TypeNum.d8) $&
-             reson &|& modu)
+           frequencyFromBendModulationPacked speed fm)
+   in  Causal.stereoFromMonoControlled CtrlPS.process $&
+          (Causal.zipWith (Moog.parameter TypeNum.d8) $&  reson &|& modu)
           &|&
-          F.fromSignal stereoNoise
+          F.fromSignal (stereoNoise sr)
 
 wind ::
    IO (SampleRate Real -> Real -> Real ->
@@ -553,17 +635,16 @@
 wind =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, ())
+         osc sr
          .
          (Zip.arrowSecond $ Zip.arrowSecond $
             arr $ transposeModulation sr freq)
          .
          zipEnvelope (env sr vel))
-      (CausalP.processIO
-         (F.withArgs $ \(env,(reson,fm)) ->
-              CausalP.envelopeStereo $&
-                 env &|&
-                 windCore reson fm))
+      (CausalRender.run $ \sr ->
+         F.withArgs $ \(env,(reson,fm)) ->
+            Stereo.multiValue <$>
+            Causal.envelopeStereo $& env &|& windCore reson fm sr)
       stringControlledEnvelope
 
 
@@ -577,35 +658,37 @@
 windPhaser =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, ())
+         osc sr
          .
          (Zip.arrowSecond $ Zip.arrowSecond $
           Zip.arrowSplit
-             (arr $ fmap (Allpass.flangerParameterPlain TypeNum.d8) .
+             (arr $ fmap (Allpass.flangerParameter TypeNum.d8) .
                     frequencyControl sr)
              (Zip.arrowSecond $
               arr $ transposeModulation sr freq))
          .
          zipEnvelope (env sr vel))
-      (CausalP.processIO
+      (CausalRender.run $ \sr ->
          (F.withArgs $ \(env,(phaserMix0,(phaserFreq,(reson,fm)))) ->
-          let phaserMix = CausalP.mapSimple Serial.upsample $& phaserMix0
-              noise = windCore reson fm
+          let phaserMix = Causal.map Serial.upsample $& phaserMix0
+              noise = windCore reson fm sr
 
-          in  CausalP.envelopeStereo $&
+          in Stereo.multiValue <$>
+              Causal.envelopeStereo $&
                  env &|&
-                 ((CausalP.envelopeStereo $& (1 - phaserMix) &|& noise)
+                 ((Causal.envelopeStereo $& (1 - phaserMix) &|& noise)
                   +
-                  (CausalP.envelopeStereo $&
+                  (Causal.envelopeStereo $&
                      phaserMix &|&
                      (Stereo.arrowFromMonoControlled CtrlPS.process $&
-                        phaserFreq &|& noise)))))
+                        (Allpass.cascadeParameterUnMultiValue <$> phaserFreq)
+                        &|& noise)))))
       stringControlledEnvelope
 
 
 phaserOsci ::
-   (Param.T p Real -> Param.T p Real -> CausalP.T p a VectorValue) ->
-   CausalP.T p a (Stereo.T VectorValue)
+   (Exp Real -> Exp Real -> Causal.T a VectorValue) ->
+   Causal.T a (Stereo.T VectorValue)
 phaserOsci osci =
    CausalPS.amplifyStereo 0.25
    .
@@ -632,27 +715,28 @@
 softStringShapeCore wave =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, ())
+         osc sr
          .
          (Zip.arrowSecond $ Zip.arrowSecond $
           Zip.arrowSecond $
             arr $ transposeModulation sr freq)
          .
          zipEnvelope (env sr vel))
-      (CausalP.processIO
-         (CausalP.envelopeStereo
+      (CausalRender.run $
+       constant frequency 5 $ \speed _sr ->
+         (arr Stereo.multiValue
           .
+          Causal.envelopeStereo
+          .
           second
              (F.withArgs $ \(shape0,(det0,fm)) ->
-              let det = CausalP.mapSimple Serial.upsample $& det0
-                  shape = CausalP.mapSimple Serial.upsample $& shape0
-                  modu =
-                     MIDIL.frequencyFromBendModulationPacked
-                        (frequencyConst 5) $& fm
+              let det = Causal.map Serial.upsample $& det0
+                  shape = Causal.map Serial.upsample $& shape0
+                  modu = frequencyFromBendModulationPacked speed fm
                   osci ::
-                     Param.T (mod,fm) Real ->
-                     Param.T (mod,fm) Real ->
-                     CausalP.T (mod,fm)
+                     Exp Real ->
+                     Exp Real ->
+                     Causal.T
                         (VectorValue,
                               {- wave shape parameter -}
                          (VectorValue, VectorValue)
@@ -662,9 +746,9 @@
                      CausalPS.shapeModOsci wave
                      .
                      second
-                        (CausalP.feedFst (SigPS.constant p)
+                        (CausalClass.feedFst (SigPS.constant p)
                          .
-                         CausalP.envelope
+                         Causal.envelope
                          .
                          first (one + CausalPS.amplify d))
 
@@ -709,51 +793,51 @@
 fmStringStereoFM =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, ())
+         osc sr
          .
          (Zip.arrowSecond $ Zip.arrowSecond $
           Zip.arrowSecond $
             arr $ transposeModulation sr freq)
          .
          zipEnvelope (env sr vel))
-      (CausalP.processIO
+      (CausalRender.run $
+       constant frequency 5 $ \speed _sr ->
          (F.withArgs $ \(env,((depth0,shape0),(det0,fm))) ->
-          let det = CausalP.mapSimple Serial.upsample $& det0
-              shape = CausalP.mapSimple Serial.upsample $& shape0
+          let det = Causal.map Serial.upsample $& det0
+              shape = Causal.map Serial.upsample $& shape0
               depth =
-                 CausalP.envelope $&
+                 Causal.envelope $&
                     env &|&
-                    (CausalP.mapSimple Serial.upsample $& depth0)
-              modu =
-                 MIDIL.frequencyFromBendModulationPacked
-                    (frequencyConst 5) $& fm
+                    (Causal.map Serial.upsample $& depth0)
+              modu = frequencyFromBendModulationPacked speed fm
 
               osci ::
-                 Param.T (mod,fm) Real ->
-                 Param.T (mod,fm) Real ->
-                 CausalP.T (mod,fm)
+                 Exp Real ->
+                 Exp Real ->
+                 Causal.T
                     ((VectorValue, VectorValue)
                           {- phase modulation depth, modulator distortion -},
                      (VectorValue, VectorValue)
                           {- detune, frequency modulation -})
                     VectorValue
               osci p d =
-                 CausalPS.osciSimple WaveL.approxSine2
+                 CausalPS.osci WaveL.approxSine2
                  .
-                 ((CausalP.envelope
+                 ((Causal.envelope
                   .
                   second
                      (CausalPS.shapeModOsci WaveL.rationalApproxSine1
-                        . second (CausalP.feedFst (SigPS.constant p)))
+                        . second (CausalClass.feedFst (SigPS.constant p)))
                   <<^
                   (\((dp, ds), f) -> (dp, (ds, f))))
                   &&& arr snd)
                  .
                  second
-                    (CausalP.envelope .
+                    (Causal.envelope .
                      first (one + CausalPS.amplify d))
 
-          in  CausalP.envelopeStereo $&
+          in  Stereo.multiValue <$>
+              Causal.envelopeStereo $&
                  env &|&
                  (phaserOsci osci $&  (depth &|& shape) &|& (det &|& modu))))
       stringControlledEnvelope
@@ -775,13 +859,20 @@
              Zip.arrowSecond
                 ((id :: PIOId StereoChunk)
                  .
-                 freqMod (sr, ())
+                 freqMod sr
                  .
                  (Zip.arrowSecond $ arr $
                     transposeModulation sr (freq * Sample.period pos))))
-      (CausalP.processIO (CausalP.stereoFromMono resamplingProc))
-      (CausalP.processIO
-         (F.withArgs $ stereoFrequenciesFromDetuneBendModulation (frequencyConst 3)))
+      (CausalRender.run $ \sr (amp, smp) ->
+         Stereo.multiValue
+         ^<<
+         Causal.stereoFromMono (resamplingProc sr (amp, smp))
+         <<^
+         Stereo.unMultiValue)
+      (CausalRender.run $
+       constant frequency 3 $ \speed _sr ->
+         fmap Stereo.multiValue $
+         F.withArgs $ stereoFrequenciesFromDetuneBendModulation speed)
 
 
 {- |
@@ -800,12 +891,13 @@
              Zip.arrowSecond
                 ((id :: PIOId Chunk)
                  .
-                 freqMod (sr, ())
+                 freqMod sr
                  .
                  (arr $ transposeModulation sr (freq * Sample.period pos))))
-      (CausalP.processIO resamplingProc)
-      (CausalP.processIO
-         (MIDIL.frequencyFromBendModulationPacked (frequencyConst 3)))
+      (CausalRender.run resamplingProc)
+      (CausalRender.run $
+       constant frequency 3 $ \speed _sr ->
+         F.withArgs $ frequencyFromBendModulationPacked speed)
 
 {-
 We split the frequency modulation signal
@@ -815,14 +907,14 @@
 -}
 assembleParts ::
    (CutG.Transform a, CutG.Transform b) =>
-   ((SampleRate Real, (Real, SVL.Vector Real)) -> PIO.T a b) ->
+   (SampleRate Real -> (Real, SVL.Vector Real) -> PIO.T a b) ->
    Sample.T -> SampleRate Real -> Real ->
    PIO.T (Zip.T (Gate.Chunk gate) a) b
 assembleParts osc smp sr vel =
    let pos = Sample.positions smp
        amp = 2 * amplitudeFromVelocity vel
        (attack, sustain, release) = Sample.parts smp
-       osci smpBody = osc (sr, (amp, smpBody))
+       osci smpBody = osc sr (amp, smpBody)
    in  mappend
           (osci
              (attack `SigSt.append`
@@ -832,22 +924,20 @@
           (osci release <<^ Zip.second)
 
 resamplingProc ::
-   CausalP.T
-      (SampleRate Real, (Real, SigSt.T Real))
-      VectorValue VectorValue
-resamplingProc =
-   let amp = number fst
-       smp = signal snd
-   in  CausalPS.amplify amp
+   SampleRate (Exp Real) ->
+   (Exp Real, Sig.T (MultiValue.T Real)) ->
+   Causal.T VectorValue VectorValue
+resamplingProc _sr (amp, smp) =
+       CausalPS.amplify amp
        .
        CausalPS.pack
-          (CausalP.frequencyModulationLinear
+          (Causal.frequencyModulationLinear
              {-
-             (SigP.fromStorableVector $
+             (Sig.fromStorableVector $
                 fmap (SV.concat . SVL.chunks . SVL.take 1000000) smp)
              -}
-             (SigP.fromStorableVectorLazy smp)
-             {- (SigP.osciSimple WaveL.saw 0 (1 / 324 {- samplePeriod smp -})) -})
+             smp
+             {- (Sig.osci WaveL.saw 0 (1 / 324 {- samplePeriod smp -})) -})
 
 helixSound ::
    IO (Sample.T ->
@@ -857,7 +947,7 @@
               (Zip.T (Control Real) DetuneBendModControl))
           StereoChunk)
 helixSound =
-   liftM4
+   App.lift4
       (\helix zigZag integrate freqMod smp sr vel freq ->
          let pos = Sample.positions smp
              amp = 2 * amplitudeFromVelocity vel
@@ -875,16 +965,17 @@
                 (fromIntegral $ Sample.start pos,
                  fromIntegral $ Sample.loopStart pos,
                  fromIntegral $ Sample.loopLength pos)
-         in  helix (sr, ((amp, Sample.period pos), Sample.body smp))
+         in  helix sr amp (Sample.period pos)
+                (Render.buffer $ SV.concat $ SVL.chunks $ Sample.body smp)
              .
              Zip.arrowFirstShorten
                 (mappend
-                    (zigZag (sr, poss) . Gate.shorten)
-                    (integrate (sr, (releaseStart, releaseStop))
+                    (zigZag sr poss . Gate.shorten)
+                    (integrate sr (releaseStart, releaseStop)
                         <<^ Zip.second))
              .
              Zip.arrowSecond
-                (freqMod (sr, ())
+                (freqMod sr
                  .
                  (Zip.arrowSecond $ arr $ transposeModulation sr freq))
              .
@@ -893,52 +984,56 @@
       makeHelix
       makeZigZag
       makeIntegrate
-      (CausalP.processIO
-         (F.withArgs $ stereoFrequenciesFromDetuneBendModulation (frequencyConst 3)))
+      (CausalRender.run $
+       constant frequency 3 $ \speed _sr ->
+         fmap Stereo.multiValue $
+         F.withArgs $ stereoFrequenciesFromDetuneBendModulation speed)
 
 makeHelix ::
-   IO ((SampleRate Real, ((Real, Real), SigSt.T Real)) ->
+   IO (SampleRate Real -> Real -> Real -> Render.Buffer Real ->
        PIO.T (Zip.T Chunk StereoChunk) StereoChunk)
 makeHelix =
-   CausalP.processIO $
-   ParamS.withTuple2 $
-      \((Number amp, Number per), Signal smp) ->
+   CausalRender.run $
+   wrapped $
+      \(Number amp) (Number per) (SampleRate _sr) smp ->
+           arr Stereo.multiValue
+           .
            CausalPS.amplifyStereo amp
            .
-           CausalP.stereoFromMono
+           Causal.stereoFromMono
               (Helix.staticPacked
                   Interpolation.linear
                   Interpolation.linear
-                  (fmap round per) per
-                  (fmap (SV.concat . SVL.chunks) smp)
+                  (Expr.roundToIntFast per) per
+                  smp
                .
                second (CausalPS.osciCore $< 0))
            .
-           arr (\(shape, freq) -> fmap ((,) shape) freq)
+           arr (\(shape, freq) -> (,) shape <$> Stereo.unMultiValue freq)
 
 makeZigZag ::
-   IO ((SampleRate Real, (Real, Real, Real)) ->
+   IO (SampleRate Real -> (Real, Real, Real) ->
        PIO.T (Control Real) Chunk)
 makeZigZag =
-   CausalP.processIO $
-   ParamS.withTuple2 $
-      \(Number start, Number loopStart, Number loopLength) ->
+   CausalRender.run $
+   wrapped $
+      \(Number start, Number loopStart, Number loopLength) (SampleRate _sr) ->
          CausalPS.raise start
          .
          -- CausalPS.pack (Helix.zigZagLong (loopStart-start) loopLength)
          Helix.zigZagLongPacked (loopStart-start) loopLength
          .
-         CausalP.mapSimple Serial.upsample
+         Causal.map Serial.upsample
 
 makeIntegrate ::
-   IO ((SampleRate Real, (Real, Real)) ->
+   IO (SampleRate Real -> (Real, Real) ->
        PIO.T (Control Real) Chunk)
 makeIntegrate =
-   CausalP.processIO $
-   ParamS.withTuple2 $
-      \(Number start, Number stop) ->
-         CausalPV.takeWhile (\s v ->  s %> Value.lift1 Serial.subsample v) stop
+   CausalRender.run $
+   wrapped $
+      \(Number start, Number stop) (SampleRate _sr) ->
+         Causal.takeWhile (\v -> stop >* Serial.subsample v)
          .
          CausalPS.integrate start
          .
-         CausalP.mapSimple Serial.upsample
+         Causal.map Serial.upsample
diff --git a/src/Synthesizer/LLVM/Server/CausalPacked/InstrumentPlug.hs b/src/Synthesizer/LLVM/Server/CausalPacked/InstrumentPlug.hs
--- a/src/Synthesizer/LLVM/Server/CausalPacked/InstrumentPlug.hs
+++ b/src/Synthesizer/LLVM/Server/CausalPacked/InstrumentPlug.hs
@@ -4,7 +4,7 @@
 The Instruments in this module have the same causal arrow interface
 as the ones in "Synthesizer.LLVM.Server.CausalPacked.Instrument",
 but here we use the higher level interface
-of the "Synthesizer.LLVM.CausalParameterized.FunctionalPlug" module.
+of the "Synthesizer.LLVM.Causal.FunctionalPlug" module.
 -}
 module Synthesizer.LLVM.Server.CausalPacked.InstrumentPlug (
    tineStereoFM,
@@ -17,55 +17,54 @@
           pingControlledEnvelope,
           stringControlledEnvelope,
           reorderEnvelopeControl)
-import Synthesizer.LLVM.Server.CommonPacked (
-          Param, VectorValue)
+import Synthesizer.LLVM.Server.CausalPacked.Common (transposeModulation)
+import Synthesizer.LLVM.Server.CommonPacked (VectorValue)
 import Synthesizer.LLVM.Server.Common (
-          SampleRate, Real,
-          frequencyConst, timeConst,
-          number, transposeModulation)
+          SampleRate, expSampleRate, Real,
+          Arg(Number), wrapped,
+          constant, frequency, time)
 
 import qualified Synthesizer.CausalIO.Process as PIO
 
-import Synthesizer.LLVM.CausalParameterized.FunctionalPlug (($&), (&|&))
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.CausalParameterized.Helix as Helix
-import qualified Synthesizer.LLVM.CausalParameterized.FunctionalPlug as FP
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.Helix as Helix
+import qualified Synthesizer.LLVM.Causal.FunctionalPlug as FP
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Interpolation as Interpolation
 import qualified Synthesizer.LLVM.Wave as WaveL
+import Synthesizer.LLVM.Causal.FunctionalPlug (($&), (&|&))
 
 import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
 import qualified Synthesizer.LLVM.MIDI as MIDIL
 import qualified Synthesizer.Zip as Zip
 
-import qualified LLVM.DSL.Parameter as Param
-import qualified LLVM.Core as LLVM
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
 
-import qualified Data.Traversable as Trav
-import Control.Category (id, (.))
-import Control.Applicative (liftA2)
+import qualified LLVM.Extra.Multi.Value as MultiValue
 
+import Control.Category ((.))
+import Control.Applicative (liftA2, (<$>))
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base hiding (id, (.))
 
 
-type FuncP pp pl = FP.T pp (SampleRate Real, pl)
-
-
 stereoFrequenciesFromDetuneBendModulation ::
-   Param pl Real ->
-   (FuncP pp pl inp (LLVM.Value Real),
-    FuncP pp pl inp (BM.T (LLVM.Value Real))) ->
-   FuncP pp pl inp (Stereo.T VectorValue)
+   Exp Real ->
+   (FP.T p inp (MultiValue.T Real),
+    FP.T p inp (MultiValue.T (BM.T Real))) ->
+   FP.T p inp (Stereo.T VectorValue)
 stereoFrequenciesFromDetuneBendModulation speed (detune, freq) =
-   CausalP.envelopeStereo $&
-      (MIDIL.frequencyFromBendModulationPacked speed $& freq)
+   Causal.envelopeStereo $&
+      (MIDIL.frequencyFromBendModulationPacked speed $&
+         (BM.unMultiValue <$> freq))
       &|&
-      (CausalP.mapSimple (Trav.mapM Serial.upsample) $&
+      (Causal.map (fmap Serial.upsample) $&
        liftA2 Stereo.cons (one + detune) (one - detune))
 
 tineStereoFM ::
@@ -84,27 +83,30 @@
          Zip.arrowFirstShorten (env sr vel)
          .
          reorderEnvelopeControl)
-      (FP.withArgs $ \(env, ((index0,depth0), (detune,fm))) ->
-         let vel = number id
-             freqs =
+      (FP.withArgs $ \(env, ((index0,depth0), (detune,fm))) pl ->
+       (\f -> case Expr.unzip pl of (sr,vel) -> f (expSampleRate sr) vel) $
+       wrapped $ \(Number vel) ->
+       constant time 1 $ \halfLife ->
+       constant frequency 5 $ \speed _sr ->
+         let freqs =
                 stereoFrequenciesFromDetuneBendModulation
-                   (frequencyConst 5)
+                   speed
                    (FP.plug detune,
-                    FP.plug $ liftA2 (uncurry transposeModulation) FP.askParameter fm)
-             index = CausalP.mapSimple Serial.upsample $& FP.plug index0
-             depth = CausalP.mapSimple Serial.upsample $& FP.plug depth0
-             expo =
-                FP.fromSignal $
-                SigPS.exponential2 (timeConst 1) (1 + vel)
+                    FP.plug $
+                      liftA2 (uncurry transposeModulation) FP.askParameter fm)
+             index = Causal.map Serial.upsample $& FP.plug index0
+             depth = Causal.map Serial.upsample $& FP.plug depth0
+             expo = FP.fromSignal $ SigPS.exponential2 halfLife (1 + vel)
              osci freq =
-                CausalPS.osciSimple WaveL.approxSine2 $&
+                CausalPS.osci WaveL.approxSine2 $&
                    expo * depth *
-                      (CausalPS.osciSimple WaveL.approxSine2
+                      (CausalPS.osci WaveL.approxSine2
                        $& zero &|& index*freq)
                    &|&
                    freq
-         in  CausalP.envelopeStereo $&
-                FP.plug env &|& Stereo.liftApplicative osci freqs)
+         in fmap Stereo.multiValue $
+            Causal.envelopeStereo $&
+               FP.plug env &|& Stereo.liftApplicative osci freqs)
       (pingControlledEnvelope (Just 0.01))
 
 
@@ -117,30 +119,34 @@
 helixNoise =
    liftA2
       (\osc env sr vel freq ->
-         osc (sr, freq) (sr, vel)
+         osc (sr, freq) sr
          .
          Zip.arrowFirstShorten (env sr vel)
          .
          reorderEnvelopeControl)
-      (FP.withArgs $ \(env, (speed0, (detune,fm))) ->
+      (FP.withArgs $ \(env, (speed0, (detune,fm))) sr ->
+       (\f -> f (expSampleRate sr)) $
+       constant frequency 5 $ \modSpeed _sr ->
          let freqs =
                 stereoFrequenciesFromDetuneBendModulation
-                   (frequencyConst 5)
+                   modSpeed
                    (FP.plug detune,
-                    FP.plug $ liftA2 (uncurry transposeModulation) FP.askParameter fm)
-             speed = CausalP.mapSimple Serial.upsample $& FP.plug speed0
-         in  CausalP.envelopeStereo $&
-                FP.plug env &|& Stereo.liftApplicative (helixOsci speed) freqs)
+                    FP.plug $
+                      liftA2 (uncurry transposeModulation) FP.askParameter fm)
+             speed = Causal.map Serial.upsample $& FP.plug speed0
+         in fmap Stereo.multiValue $
+            Causal.envelopeStereo $&
+               FP.plug env &|& Stereo.liftApplicative (helixOsci speed) freqs)
       stringControlledEnvelope
 
 helixOsci ::
-   FP.T pp pl inp VectorValue ->
-   FP.T pp pl inp VectorValue ->
-   FP.T pp pl inp VectorValue
+   FP.T pp inp VectorValue ->
+   FP.T pp inp VectorValue ->
+   FP.T pp inp VectorValue
 helixOsci speed freq =
    CausalPS.pack
       (Helix.dynamicLimited Interpolation.cubic Interpolation.cubic
-          64 (64 :: Param.T p Real) (SigP.noise 66 0.2))
+          64 (64 :: Exp Real) (Sig.noise 66 0.2))
    $&
    speed &|&
    (CausalPS.osciCore $& 0 &|& freq)
diff --git a/src/Synthesizer/LLVM/Server/CausalPacked/Speech.hs b/src/Synthesizer/LLVM/Server/CausalPacked/Speech.hs
--- a/src/Synthesizer/LLVM/Server/CausalPacked/Speech.hs
+++ b/src/Synthesizer/LLVM/Server/CausalPacked/Speech.hs
@@ -22,25 +22,29 @@
           (StereoChunk, Control, Frequency, frequencyControl,
            WithEnvelopeControl, zipEnvelope,
            stringControlledEnvelope, pingControlledEnvelope)
-import Synthesizer.LLVM.Server.CommonPacked (VectorValue)
+import Synthesizer.LLVM.Server.CommonPacked (Vector)
 import Synthesizer.LLVM.Server.Common
-          (SampleRate(SampleRate), Real, parameter, noiseReference, frequency)
+          (SampleRate(SampleRate), Real, wrapped,
+           Arg(Frequency), constant, noiseReference)
 import qualified Synthesizer.LLVM.Server.SampledSound as Sample
 
 import qualified Synthesizer.MIDI.CausalIO.Process as MIO
 import qualified Synthesizer.CausalIO.Gate as Gate
 import qualified Synthesizer.CausalIO.Process as PIO
 
-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($>), ($*))
-import Synthesizer.LLVM.CausalParameterized.FunctionalPlug (($&), (&|&))
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Filter.Universal as UniFilterL
 import qualified Synthesizer.LLVM.Filter.NonRecursive as FiltNR
-import qualified Synthesizer.LLVM.CausalParameterized.FunctionalPlug as FP
-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.FunctionalPlug as FP
+import qualified Synthesizer.LLVM.Causal.ControlledPacked as CtrlPS
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import Synthesizer.LLVM.Causal.FunctionalPlug (($&), (&|&))
+import Synthesizer.LLVM.Causal.Process (($*), ($<), ($>))
 
 import qualified Synthesizer.Zip as Zip
 import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
@@ -57,12 +61,12 @@
 import qualified Data.StorableVector as SV
 import qualified Data.Map as Map ; import Data.Map (Map)
 
-import qualified LLVM.Core as LLVM
+import qualified LLVM.Extra.Multi.Value as MultiValue
 
 import qualified System.Path as Path
 import System.Path ((</>), (<.>))
 
-import Control.Arrow (arr, second, (^<<), (***))
+import Control.Arrow (arr, second, (^<<), (<<^), (***))
 import Control.Category ((.))
 import Control.Applicative (pure, liftA, liftA3, (<$>), (<*>))
 
@@ -111,19 +115,23 @@
          case formants p of
             Nothing -> arr $ const SV.empty
             Just fs ->
-               filt (sr, fs)
+               filt sr fs
                .
                Gate.shorten)
-      (CausalP.processIO
-         (CausalP.stereoFromMono
+      (CausalRender.run $
+       wrapped $ \(Frequency low, Frequency high) (SampleRate _sr) ->
+         Stereo.multiValue
+         ^<<
+         Causal.stereoFromMono
              (let lowpass q f =
                      UniFilter.bandpass
                      ^<<
                      CtrlPS.process
                      $<
-                     SigP.constant
-                        (UniFilter.parameter . Pole q ^<< frequency f)
-              in  lowpass 100 fst + lowpass 20 snd)))
+                     Sig.constant (UniFilter.parameter $ Pole q f)
+              in  lowpass 100 low + lowpass 20 high)
+         <<^
+         Stereo.unMultiValue)
 
 formants :: VoiceMsg.Pitch -> Maybe (Real, Real)
 formants p =
@@ -146,15 +154,16 @@
    IO (Map VoiceMsg.Pitch (SV.Vector Real) -> VowelSynth)
 vowelMask =
    liftA
-      (\filt dict sr p ->
+      (\filt dict _sr p ->
          case Map.lookup p dict of
             Nothing -> arr $ const SV.empty
-            Just mask ->
-               filt (sr, mask)
-               .
-               Gate.shorten)
-      (CausalP.processIO
-         (CausalP.stereoFromMono (FiltNR.convolvePacked (parameter id))))
+            Just mask -> filt (Render.buffer mask) . Gate.shorten)
+      (CausalRender.run $ \mask ->
+         Stereo.multiValue
+         ^<<
+         Causal.stereoFromMono (FiltNR.convolvePacked mask)
+         <<^
+         Stereo.unMultiValue)
 
 
 type
@@ -183,53 +192,57 @@
          case Map.lookup p dict of
             Nothing -> arr $ const SV.empty
             Just (typ, mask) ->
+               let maskBuf = Render.buffer mask in
                case typ of
                   Filtered env carrier ->
                      (case carrier of
-                        Voiced -> filt (sr, mask)
-                        Unvoiced -> filtNoise (sr, mask) . arr Zip.first
+                        Voiced -> filt maskBuf
+                        Unvoiced -> filtNoise sr maskBuf . arr Zip.first
                         Rasp ->
-                           filtRasp (sr, (mask,
+                           filtRasp maskBuf $
                               case sr of
                                  SampleRate r ->
                                     SVL.cycle $ SVL.take (round $ r/20) $
                                     CtrlG.exponential SigG.defaultLazySize
-                                       (r/40) 1)))
+                                       (r/40) 1)
                      .
                      zipEnvelope
                         (case env of
                            Continuous -> contEnv sr vel
                            Percussive -> percEnv sr vel)
                   Sampled ->
-                     smp (sr, SVL.fromChunks $ repeat mask)
+                     smp (SVL.fromChunks $ repeat mask)
                      .
                      arr Zip.first
                      .
                      zipEnvelope (contEnv sr vel))
-   <*> CausalP.processIO
-         (CausalP.envelopeStereo
+   <*> (CausalRender.run $ \mask ->
+         Stereo.multiValue <$>
+          Causal.envelopeStereo
           .
           second
-             (CausalP.stereoFromMono (FiltNR.convolvePacked (parameter id))))
-   <*> CausalP.processIO
-         (CausalP.envelopeStereo
+             (Causal.stereoFromMono (FiltNR.convolvePacked mask)
+                  <<^ Stereo.unMultiValue))
+   <*> (CausalRender.run $ \mask env ->
+         Stereo.multiValue <$>
+          Causal.envelopeStereo
           .
-          ((CausalP.envelope
-              $< SigPS.pack (SigP.fromStorableVectorLazy (parameter snd)))
+          ((Causal.envelope $< SigPS.pack env)
            ***
-           CausalP.stereoFromMono (FiltNR.convolvePacked (parameter fst))))
-   <*> CausalP.processIO
-         (CausalP.envelopeStereo $>
+           (Causal.stereoFromMono (FiltNR.convolvePacked mask)
+               <<^ Stereo.unMultiValue)))
+   <*> (CausalRender.run $
+        constant noiseReference 1e7 $ \noiseRef _sr mask ->
+         Stereo.multiValue <$>
+         Causal.envelopeStereo $>
              traverse
                 (\seed ->
-                   FiltNR.convolvePacked (parameter id) $*
-                   (SigPS.noise seed $ noiseReference 1e7))
+                   FiltNR.convolvePacked mask $* SigPS.noise seed noiseRef)
                 (Stereo.cons 42 23))
-   <*> CausalP.processIO
-         (let smp = parameter id
-          in  pure ^<<
-              (CausalP.envelope $>
-                 (SigPS.pack $ SigP.fromStorableVectorLazy smp)))
+   <*> (CausalRender.run $ \smp ->
+         (\x -> Stereo.consMultiValue x x)
+         ^<<
+         (Causal.envelope $> SigPS.pack smp))
    <*> stringControlledEnvelope
    <*> pingControlledEnvelope (Just 0.01)
 
@@ -422,8 +435,9 @@
 plugUniFilterParameter ::
    Input a (Control Real) ->
    Input a (Control Frequency) ->
-   FP.T (SampleRate Real) pl a (UniFilter.Parameter (LLVM.Value Real))
+   FP.T (SampleRate Real) a (UniFilter.Parameter (MultiValue.T Real))
 plugUniFilterParameter reson freq =
+   fmap UniFilterL.unMultiValueParameter $
    FP.plug $
    liftA3
       (\resonChunk freqChunk sr ->
@@ -441,16 +455,17 @@
    (Input inp (Control Real),
       (Input inp (Control Real), Input inp (Control Frequency))) ->
    Input inp StereoChunk ->
-   FP.T (SampleRate Real) pl inp (Stereo.T VectorValue)
+   FP.T (SampleRate Real) inp (MultiValue.T (Stereo.T Vector))
 singleFormant (amp, (reson, freq)) x =
-   CausalP.envelopeStereo $&
-      (CausalP.mapSimple Serial.upsample $& FP.plug amp)
+   Stereo.multiValue <$>
+   Causal.envelopeStereo $&
+      (Causal.map Serial.upsample $& FP.plug amp)
       &|&
-      (CausalP.stereoFromMonoControlled
+      (Causal.stereoFromMonoControlled
            (UniFilter.bandpass ^<< CtrlPS.process) $&
          plugUniFilterParameter reson freq
          &|&
-         FP.plug x)
+         (Stereo.unMultiValue <$> FP.plug x))
 
 filterFormant ::
    IO (SampleRate Real ->
@@ -459,8 +474,8 @@
           StereoChunk)
 filterFormant =
    liftA
-      (\filt sr -> filt sr (sr, ()))
-      (FP.withArgs $ \(fmt, x) -> singleFormant fmt x)
+      (\filt sr -> filt sr ())
+      (FP.withArgs $ \(fmt, x) _unit -> singleFormant fmt x)
 
 filterFormants ::
    IO (SampleRate Real ->
@@ -473,6 +488,6 @@
              StereoChunk)
 filterFormants =
    liftA
-      (\filt sr -> filt sr (sr, ()))
-      (FP.withArgs $ \((fmt0, (fmt1, (fmt2, (fmt3, fmt4)))), x) ->
+      (\filt sr -> filt sr ())
+      (FP.withArgs $ \((fmt0, (fmt1, (fmt2, (fmt3, fmt4)))), x) _unit ->
          foldl1 (+) $ map (flip singleFormant x) [fmt0, fmt1, fmt2, fmt3, fmt4])
diff --git a/src/Synthesizer/LLVM/Server/CausalPacked/SpeechExplore.hs b/src/Synthesizer/LLVM/Server/CausalPacked/SpeechExplore.hs
--- a/src/Synthesizer/LLVM/Server/CausalPacked/SpeechExplore.hs
+++ b/src/Synthesizer/LLVM/Server/CausalPacked/SpeechExplore.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 module Main where
 
-import Synthesizer.LLVM.Server.Common (Real)
+import Synthesizer.LLVM.Server.Common (Real, pioApply)
 
 import qualified Synthesizer.LLVM.Server.SampledSound as Sample
 import qualified Sound.Sox.Write as SoxWrite
@@ -11,13 +11,18 @@
 import qualified Graphics.Gnuplot.Plot.TwoDimensional as Plot2D
 import qualified Graphics.Gnuplot.Graph.TwoDimensional as Graph2D
 
-import qualified Synthesizer.LLVM.CausalParameterized.Controlled as CtrlP
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1
+import qualified Synthesizer.LLVM.Causal.Controlled as Ctrl
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Filter.Universal as UniFilterL
 import qualified Synthesizer.LLVM.Filter.NonRecursive as FiltNR
-import Synthesizer.LLVM.Causal.Process (($*), ($<), ($<#))
+import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1
+import Synthesizer.LLVM.Causal.Process (($*), ($<))
 
+import qualified LLVM.DSL.Expression as Expr
+
 import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilter
 import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as FirstOrder
 import Synthesizer.Plain.Filter.Recursive (Pole(Pole))
@@ -35,8 +40,8 @@
 import qualified Data.StorableVector.Lazy as SVL
 import qualified Data.StorableVector as SV
 
-import Control.Arrow (arr, (<<<), (^<<))
-import Control.Category ((.), id)
+import Control.Arrow ((<<<), (^<<))
+import Control.Category ((.))
 import Control.Applicative ((<$>))
 
 import Control.Functor.HT (void)
@@ -48,7 +53,9 @@
 import Data.Maybe (catMaybes)
 import Data.Tuple.HT (mapSnd)
 import Data.Ord.HT (comparing)
-import Data.Monoid (mempty, mappend)
+import Data.Semigroup ((<>))
+import Data.Monoid (mempty)
+import Data.Word (Word)
 
 import qualified System.Path.PartClass as PathClass
 import qualified System.Path as Path
@@ -144,20 +151,20 @@
    (UniFilter.lowpass, Pole 2 3000, 0.6) :
    []
 
-synthesis :: IO (SVL.ChunkSize -> () -> SVL.Vector Real)
+synthesis :: IO (SVL.ChunkSize -> SVL.Vector Real)
 synthesis =
-   SigP.runChunky $
+   Render.run $
       (sum (map (\(typ, Pole q f, amp) ->
-                   CausalP.amplify (return amp)
+                   Causal.amplify (Expr.cons amp)
                    <<<
                    typ
                    ^<<
-                   CtrlP.process
+                   Ctrl.process
                    $<
-                   (SigP.constant $ return $
-                    UniFilter.parameter $ Pole q $ f / sampleRate))
+                   (fmap UniFilterL.unMultiValueParameter $ Sig.constant $
+                    Expr.cons $ UniFilter.parameter $ Pole q $ f / sampleRate))
                 formants_sch)
-        $* SigP.noise 174373 0.02)
+        $* Sig.noise 174373 0.02)
 
 compareSpec ::IO ()
 compareSpec = do
@@ -165,39 +172,45 @@
    synthesized <- synthesis
    void $ Plot.plot WXT.cons $
       spectrumPlot sampled
-      `mappend`
+      <>
       spectrumPlot
          (SVL.take (SVL.length sampled) $
-          synthesized (SVL.chunkSize 4096) ())
+          synthesized (SVL.chunkSize 4096))
 
 render ::IO ()
 render = do
    synthesized <- synthesis
    saveSound (Path.relFile "sch-synth.wav") $
       SVL.take sampleRateInt $
-      synthesized (SVL.chunkSize 4096) ()
+      synthesized (SVL.chunkSize 4096)
 
 
 -- * purification of sampled periods
 
 -- ** using a comb filter
 
-type Comb = (Real, Int) -> SVL.Vector Real -> SVL.Vector Real
+type Comb = Real -> Word -> SVL.Vector Real -> SVL.Vector Real
 
 makeComb :: IO Comb
 makeComb =
-   CausalP.runStorableChunky $ CausalP.comb (arr fst) (arr snd)
+   (\proc gain time -> pioApply (proc gain time))
+   <$>
+   CausalRender.run Causal.comb
 
 makeHighComb :: IO Comb
 makeHighComb =
-   CausalP.runStorableChunky $
-      CausalP.comb (arr fst) (arr snd)
+   fmap (\proc gain time -> pioApply (proc gain time))
+   $
+   CausalRender.run $ \gain time ->
+      Causal.comb gain time
       .
-      (Filt1.highpassCausal $<# FirstOrder.parameter (1000/sampleRate))
+      (Filt1.highpassCausal $<
+         Sig.constant (FirstOrder.parameter (1000 / Expr.cons sampleRate)))
 
-scorePeriod :: Comb -> Real -> Int -> SVL.Vector Real -> (Real, SVL.Vector Real)
+scorePeriod ::
+   Comb -> Real -> Word -> SVL.Vector Real -> (Real, SVL.Vector Real)
 scorePeriod comb gain period sig =
-   let end = SVL.takeEnd (3*period) $ comb (gain, period) sig
+   let end = SVL.takeEnd (3 * fromIntegral period) $ comb gain period sig
    in  (Analysis.volumeEuclideanSqr end, end)
 
 vowelNames :: [String]
@@ -258,7 +271,7 @@
 findPeriod :: Comb -> SVL.Vector Real -> SVL.Vector Real
 findPeriod comb sampled =
    normalize $
-   uncurry bestRotation $
+   uncurry (bestRotation . fromIntegral) $
    mapSnd snd $
    List.maximumBy (comparing (fst . snd)) $
    flip map [350 .. 400] $ \period ->
@@ -275,7 +288,9 @@
 
 makeFilter :: IO (SV.Vector Real -> SVL.Vector Real -> SVL.Vector Real)
 makeFilter =
-   CausalP.runStorableChunky $ FiltNR.convolve id
+   (\proc mask -> pioApply (proc (Render.buffer mask)))
+   <$>
+   CausalRender.run FiltNR.convolve
 
 normalizeMax :: SVL.Vector Real -> SVL.Vector Real
 normalizeMax = FiltNRG.normalize Analysis.volumeMaximum
diff --git a/src/Synthesizer/LLVM/Server/Common.hs b/src/Synthesizer/LLVM/Server/Common.hs
--- a/src/Synthesizer/LLVM/Server/Common.hs
+++ b/src/Synthesizer/LLVM/Server/Common.hs
@@ -1,135 +1,332 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE EmptyDataDecls #-}
 module Synthesizer.LLVM.Server.Common (
-   Real, Param,
-   SampleRate(SampleRate),
+   Real,
+   SampleRate(SampleRate), expSampleRate,
    Instrument,
-   frequency, time, noiseReference, number, control, signal, parameter,
-   frequencyConst, timeConst,
+   ($+),
+   constant, ($++),
+   frequency, time, noiseReference, number,
+   Quantity(..), Arg(..), Frequency, Time, Number,
+   Input(..), InputArg(..), Parameter, Control, Signal,
+   ArgTuple(..),
+   Wrapped(..),
+   amplitudeFromVelocity,
    ($/),
 
-   chopEvents,
    piecewiseConstant,
    transposeModulation,
-   amplitudeFromVelocity,
 
+   pioApply,
+   pioApplyCont,
+   pioApplyToLazyTime,
+
    controllerAttack, controllerDetune, controllerTimbre0, controllerTimbre1,
    controllerFilterCutoff, controllerFilterResonance,
    controllerVolume,
    ) where
 
-import qualified Sound.MIDI.Controller as Ctrl
-import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import Synthesizer.LLVM.Causal.Process (($*))
 
+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
+import qualified Synthesizer.LLVM.ConstantPiece as Const
 import qualified Synthesizer.MIDI.Storable as MidiSt
+import qualified Synthesizer.MIDI.EventList as Ev
 import qualified Synthesizer.PiecewiseConstant.Signal as PC
-import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
+import qualified Synthesizer.CausalIO.Process as PIO
+import qualified Synthesizer.Generic.Signal as SigG
 
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified LLVM.DSL.Parameter as Param
+import qualified Sound.MIDI.Controller as Ctrl
+import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
 
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
 
-import qualified Synthesizer.Storable.Signal as SigSt
+import qualified LLVM.Extra.Multi.Value.Marshal as Marshal
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
 
-import qualified Data.EventList.Relative.TimeTime as EventListTT
+import qualified Data.StorableVector.Lazy as SVL
+import qualified Data.StorableVector as SV
+import Foreign.Storable (Storable)
 
-import qualified Numeric.NonNegative.Class as NonNeg
+import qualified Numeric.NonNegative.Chunky as NonNegChunky
+import qualified Numeric.NonNegative.Wrapper as NonNegW
 
-import Control.Arrow (arr, (^<<))
+import Control.Applicative (Applicative, liftA2, pure, (<*>), (<$>))
 
-import Prelude hiding (Real)
+import qualified Data.Traversable as Trav
+import qualified Data.Foldable as Fold
 
+import qualified System.Unsafe as Unsafe
 
+import qualified Algebra.Transcendental as Trans
+import qualified Algebra.Field as Field
+import qualified Algebra.Ring as Ring
 
+import NumericPrelude.Numeric
+import NumericPrelude.Base
+import Prelude ()
+
+
+
+type Real = Float
+
+type Instrument a sig = SampleRate a -> MidiSt.Instrument a sig
+
+
 newtype SampleRate a = SampleRate a
    deriving (Show)
 
 instance Functor SampleRate where
    fmap f (SampleRate sr) = SampleRate (f sr)
 
+instance Fold.Foldable SampleRate where
+   foldMap f (SampleRate sr) = f sr
 
-type Real = Float
+instance Trav.Traversable SampleRate where
+   traverse f (SampleRate sr) = SampleRate <$> f sr
 
-type Param p = Param.T (SampleRate Real, p)
+instance Applicative SampleRate where
+   pure = SampleRate
+   SampleRate f <*> SampleRate sr = SampleRate $ f sr
 
-type Instrument a sig = SampleRate a -> MidiSt.Instrument a sig
 
+instance (Render.RunArg a) => Render.RunArg (SampleRate a) where
+   type DSLArg (SampleRate a) = SampleRate (Render.DSLArg a)
+   buildArg =
+      case Render.buildArg of
+         Render.BuildArg pass create ->
+            Render.BuildArg
+               (SampleRate . pass)
+               (\(SampleRate sr) -> create sr)
 
-frequency :: (p -> Real) -> Param p Real
-frequency param =
-   arr (\(SampleRate sampleRate, p) -> param p / sampleRate)
+instance (MultiValue.C a) => MultiValue.C (SampleRate a) where
+   type Repr (SampleRate a) = MultiValue.Repr a
+   cons = multiValueSampleRate . fmap MultiValue.cons
+   undef = multiValueSampleRate $ pure MultiValue.undef
+   zero = multiValueSampleRate $ pure MultiValue.zero
+   phi bb =
+      fmap multiValueSampleRate .
+      Trav.traverse (MultiValue.phi bb) . unMultiValueSampleRate
+   addPhi bb a b =
+      Fold.sequence_ $
+      liftA2 (MultiValue.addPhi bb)
+         (unMultiValueSampleRate a) (unMultiValueSampleRate b)
 
-time :: (p -> Real) -> Param p Real
-time param =
-   arr (\(SampleRate sampleRate, p) -> param p * sampleRate)
+instance (Marshal.C a) => Marshal.C (SampleRate a) where
+   pack (SampleRate a) = Marshal.pack a
+   unpack = SampleRate . Marshal.unpack
 
-noiseReference :: Real -> Param p Real
-noiseReference freq =
-   arr (\(SampleRate sampleRate, _p) -> sampleRate/freq)
+multiValueSampleRate ::
+   SampleRate (MultiValue.T a) -> MultiValue.T (SampleRate a)
+multiValueSampleRate (SampleRate (MultiValue.Cons a)) = MultiValue.Cons a
 
-number :: (p -> Real) -> Param p Real
-number param = arr (param . snd)
+unMultiValueSampleRate ::
+   MultiValue.T (SampleRate a) -> SampleRate (MultiValue.T a)
+unMultiValueSampleRate (MultiValue.Cons a) = SampleRate (MultiValue.Cons a)
 
-control :: (p -> PC.T Real) -> Param p (PC.T Real)
-control param = arr (param . snd)
 
-signal :: (p -> SigSt.T a) -> Param p (SigSt.T a)
-signal param = arr (param . snd)
+expSampleRate :: Exp (SampleRate a) -> SampleRate (Exp a)
+expSampleRate = SampleRate . Expr.lift1 MultiValue.cast
 
-parameter :: (p -> a) -> Param p a
-parameter param = arr (param . snd)
 
 
-frequencyConst :: Real -> Param p Real
-frequencyConst param =
-   arr (\(SampleRate sampleRate, _p) -> param / sampleRate)
+($/) :: (Functor f) => f (a -> b) -> a -> f b
+f $/ x = fmap ($ x) f
 
-timeConst :: Real -> Param p Real
-timeConst param =
-   arr (\(SampleRate sampleRate, _p) -> param * sampleRate)
 
+infixr 0 $+, $++
 
+($+) ::
+   (SampleRate a -> b -> c) ->
+   (c -> SampleRate a -> d) ->
+   SampleRate a -> b -> d
+(p$+f) sampleRate param = f (p sampleRate param) sampleRate
 
-($/) :: (Functor f) => f (a -> b) -> a -> f b
-f $/ x = fmap ($x) f
+($++) ::
+   (SampleRate a -> b -> c, b) ->
+   (c -> SampleRate a -> d) ->
+   SampleRate a -> d
+((p,param)$++f) sampleRate = f (p sampleRate param) sampleRate
 
+constant ::
+   (SampleRate a -> b -> c) -> b ->
+   (c -> SampleRate a -> d) ->
+   SampleRate a -> d
+constant p param f sampleRate = f (p sampleRate param) sampleRate
 
--- might be moved to event-list package
-chopEvents ::
-   (NonNeg.C time, Num time) =>
-   time ->
-   EventListTT.T time body ->
-   [EventListTT.T time body]
-chopEvents chunkSize =
-   let go evs =
-          let (chunk,rest) = EventListTT.splitAtTime chunkSize evs
-          in  if EventListTT.duration chunk == 0
-                then []
-                else chunk : go rest
-   in  go
 
+frequency :: (Field.C a) => SampleRate a -> a -> a
+frequency (SampleRate sr) param = param / sr
 
-piecewiseConstant ::
-   (Marshal.C a, Tuple.ValueOf a ~ al) =>
-   Param.T p (PC.T a) -> SigP.T p al
-piecewiseConstant pc =
-   SigP.piecewiseConstant
-      (PC.subdivideLongStrict ^<< pc)
+time :: (Ring.C a) => SampleRate a -> a -> a
+time (SampleRate sr) param = param * sr
 
-transposeModulation ::
-   (Functor stream) =>
-   SampleRate Real ->
-   Real ->
-   stream (BM.T Real) ->
-   stream (BM.T Real)
-transposeModulation (SampleRate sampleRate) freq =
-   fmap (BM.shift (freq/sampleRate))
+noiseReference :: (Field.C a) => SampleRate a -> a -> a
+noiseReference (SampleRate sr) freq = sr/freq
 
+number :: SampleRate a -> a -> a
+number = flip const
 
+
+data Number
+data Frequency
+data Time
+data NoiseReference
+
+class Quantity quantity a where
+   data Arg quantity a
+   eval :: SampleRate a -> a -> Arg quantity a
+
+instance Quantity Number a where
+   data Arg Number a = Number a
+   eval sampleRate a = Number $ number sampleRate a
+
+instance (Field.C a) => Quantity Frequency a where
+   data Arg Frequency a = Frequency a
+   eval sampleRate a = Frequency $ frequency sampleRate a
+
+instance (Ring.C a) => Quantity Time a where
+   data Arg Time a = Time a
+   eval sampleRate a = Time $ time sampleRate a
+
+instance (Field.C a) => Quantity NoiseReference a where
+   data Arg NoiseReference a = NoiseReference a
+   eval sampleRate a = NoiseReference $ noiseReference sampleRate a
+
+
+class Input signal a where
+   data InputArg signal a
+   type InputSource signal a
+   evalInput :: SampleRate a -> InputSource signal a -> InputArg signal a
+
+data Parameter b
+
+instance Input (Parameter b) a where
+   data InputArg (Parameter b) a = Parameter b
+   type InputSource (Parameter b) a = b
+   evalInput _sr = Parameter
+
+data Control b
+
+instance Input (Control b) a where
+   data InputArg (Control b) a = Control (Sig.T b)
+   type InputSource (Control b) a = Sig.T b
+   evalInput _sr = Control
+
+data Signal b
+
+instance Input (Signal b) a where
+   data InputArg (Signal b) a = Signal (Sig.T b)
+   type InputSource (Signal b) a = Sig.T b
+   evalInput _sr = Signal
+
+
+class ArgTuple a tuple where
+   type ArgPlain tuple
+   evalTuple :: SampleRate a -> ArgPlain tuple -> tuple
+
+instance (Quantity quantity b, a ~ b) => ArgTuple a (Arg quantity b) where
+   type ArgPlain (Arg quantity b) = b
+   evalTuple = eval
+
+instance (Input signal b, a ~ b) => ArgTuple a (InputArg signal b) where
+   type ArgPlain (InputArg signal b) = InputSource signal b
+   evalTuple = evalInput
+
+instance (ArgTuple a b, ArgTuple a c) => ArgTuple a (b,c) where
+   type ArgPlain (b,c) = (ArgPlain b, ArgPlain c)
+   evalTuple sampleRate (b,c) = (evalTuple sampleRate b, evalTuple sampleRate c)
+
+instance (ArgTuple a b, ArgTuple a c, ArgTuple a d) => ArgTuple a (b,c,d) where
+   type ArgPlain (b,c,d) = (ArgPlain b, ArgPlain c, ArgPlain d)
+   evalTuple sampleRate (b,c,d) =
+      (evalTuple sampleRate b, evalTuple sampleRate c, evalTuple sampleRate d)
+
+
+
+class Wrapped a f where
+   type Unwrapped f
+   wrapped :: f -> SampleRate a -> Unwrapped f
+
+instance (a ~ b) => Wrapped a (SampleRate b -> f) where
+   type Unwrapped (SampleRate b -> f) = f
+   wrapped f = f
+
+instance
+   (a ~ b, Quantity quantity b, Wrapped a f) =>
+      Wrapped a (Arg quantity b -> f) where
+   type Unwrapped (Arg quantity b -> f) = b -> Unwrapped f
+   wrapped f sampleRate arg =
+      wrapped (f (eval sampleRate arg)) sampleRate
+
+instance
+   (a ~ b, Input signal b, Wrapped a f) =>
+      Wrapped a (InputArg signal b -> f) where
+   type Unwrapped (InputArg signal b -> f) =
+         InputSource signal b -> Unwrapped f
+   wrapped f sampleRate arg =
+      wrapped (f (evalInput sampleRate arg)) sampleRate
+
+instance
+   (ArgTuple a b, ArgTuple a c, Wrapped a f) =>
+      Wrapped a ((b,c) -> f) where
+   type Unwrapped ((b,c) -> f) = (ArgPlain b, ArgPlain c) -> Unwrapped f
+   wrapped f sampleRate arg =
+      wrapped (f (evalTuple sampleRate arg)) sampleRate
+
+instance
+   (ArgTuple a b, ArgTuple a c, ArgTuple a d, Wrapped a f) =>
+      Wrapped a ((b,c,d) -> f) where
+   type Unwrapped ((b,c,d) -> f) =
+         (ArgPlain b, ArgPlain c, ArgPlain d) -> Unwrapped f
+   wrapped f sampleRate arg =
+      wrapped (f (evalTuple sampleRate arg)) sampleRate
+
+
 {-# INLINE amplitudeFromVelocity #-}
-amplitudeFromVelocity :: Real -> Real
-amplitudeFromVelocity vel = 4**vel
+amplitudeFromVelocity :: (Trans.C a) => a -> a
+amplitudeFromVelocity vel = fromInteger 4 ^? vel
+
+
+piecewiseConstant :: (Memory.C a) => Sig.T (Const.T a) -> Sig.T a
+piecewiseConstant = Const.flatten
+
+transposeModulation :: (Field.C a, Expr.Aggregate a am) =>
+   SampleRate a -> a -> Sig.T (Const.T (BM.T am)) -> Sig.T (Const.T (BM.T am))
+transposeModulation (SampleRate sampleRate) freq xs =
+   Const.causalMap (BM.shift (freq/sampleRate)) $* xs
+
+
+
+pioApply ::
+   (Storable a, Storable b) =>
+   PIO.T (SV.Vector a) (SV.Vector b) -> SVL.Vector a -> SVL.Vector b
+pioApply = pioApplyCont (const SVL.empty)
+
+pioApplyCont ::
+   (Storable a, Storable b) =>
+   (SVL.Vector a -> SVL.Vector b) ->
+   PIO.T (SV.Vector a) (SV.Vector b) -> SVL.Vector a -> SVL.Vector b
+pioApplyCont cont proc sig = Unsafe.performIO $ do
+   act <- PIO.runStorableChunkyCont proc
+   return $ act cont sig
+
+pioApplyToLazyTime ::
+   (Storable b) =>
+   PIO.T SigG.LazySize (SV.Vector b) -> Ev.LazyTime -> SVL.Vector b
+pioApplyToLazyTime proc sig = Unsafe.performIO $ do
+   act <- PIO.runCont proc
+   return $ SVL.fromChunks $ act (const []) $
+      map (SigG.LazySize . NonNegW.toNumber) $
+      concatMap PC.chopLongTime $ NonNegChunky.toChunks sig
+
 
 
 controllerAttack, controllerDetune, controllerTimbre0, controllerTimbre1,
diff --git a/src/Synthesizer/LLVM/Server/CommonPacked.hs b/src/Synthesizer/LLVM/Server/CommonPacked.hs
--- a/src/Synthesizer/LLVM/Server/CommonPacked.hs
+++ b/src/Synthesizer/LLVM/Server/CommonPacked.hs
@@ -1,26 +1,19 @@
-module Synthesizer.LLVM.Server.CommonPacked (
-   module Synthesizer.LLVM.Server.CommonPacked,
-   Param,
-   ) where
+module Synthesizer.LLVM.Server.CommonPacked where
 
 import Synthesizer.LLVM.Server.Common
 
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
 
 import qualified Data.NonEmpty as NonEmpty
 
-import qualified Algebra.Additive as Additive
-
 import qualified Type.Data.Num.Decimal as TypeNum
 
-import Control.Arrow (arr)
+import qualified Algebra.Field as Field
+import qualified Algebra.Additive as Additive
 
-import NumericPrelude.Numeric ((+), (-), (*))
-import Prelude hiding (Real, (+), (-), (*))
+import NumericPrelude.Numeric
+import NumericPrelude.Base
+import Prelude ()
 
 
 sumNested :: (Additive.C a) => [a] -> a
@@ -36,27 +29,19 @@
    in  n + 0.01*r
 
 
-type SigP p = SigP.T (SampleRate Real, p)
-type CausalP p = CausalP.T (SampleRate Real, p)
-type FuncP p = F.T (SampleRate Real, p)
-
-
-type Vector = Serial.Plain VectorSize Real
+type Vector = Serial.T VectorSize Real
 type VectorValue = Serial.Value VectorSize Real
 type VectorSize = TypeNum.D4
 
 
+-- ToDo: generalize to Integral class
 vectorSize :: Int
 vectorSize =
    TypeNum.integralFromSingleton
       (TypeNum.singleton :: TypeNum.Singleton VectorSize)
 
-vectorRate :: Fractional a => SampleRate a -> a
-vectorRate (SampleRate sampleRate) =
-   sampleRate / fromIntegral vectorSize
-
+vectorRate :: (Field.C a) => SampleRate a -> a
+vectorRate (SampleRate sr) = sr / fromIntegral vectorSize
 
-vectorTime :: (p -> Real) -> Param p Real
-vectorTime param =
-   arr (\(SampleRate sampleRate, p) ->
-          param p * sampleRate / fromIntegral vectorSize)
+vectorTime :: (Field.C a) => SampleRate a -> a -> a
+vectorTime (SampleRate sr) param = param * sr / fromIntegral vectorSize
diff --git a/src/Synthesizer/LLVM/Server/Packed/Instrument.hs b/src/Synthesizer/LLVM/Server/Packed/Instrument.hs
--- a/src/Synthesizer/LLVM/Server/Packed/Instrument.hs
+++ b/src/Synthesizer/LLVM/Server/Packed/Instrument.hs
@@ -13,1489 +13,1494 @@
 
 
 instruments:
-   use a greymap picture as source of waveforms
-   mix of detuned noisy-waverforms, try different and uniform waveforms
-   mix of sawtooth, where every sawtooth is modulated with red noise
-   mix of sine with harmonics where every harmonic is modulated differently
-   Flute: sine + filtered noise
-   Drum with various parameters
-   derive percussive instruments from fmString and arcString (for bass synths)
-   an FM sound with a slowly changing timbre
-      by using a very slightly detuned frequency for the modulator
-   making a tone out of noise using time stretch with helix algorithm
-      a chorus effect could be applied by two successive helix stretches
-      or by mixture of two stretches signals
-      additionally a resonant filter could be applied
-   a kind of Karplus-Strong algorithm with a non-linear function of past values
-      e.g. y(t) = f(y(t-d), y(t-2*d))
-      where d is the tone period and f is non-linear, maybe chaotic function.
-      In order to limit the appearance of chaotic waveforms,
-      we could combine this with a lowpass filter.
-   let attack and release depend on On and Off velocity
-   tineStereoFM:
-      continuous control of the modulation index
-      by linear interpolation of waves between modulations with integral indices.
-      E.g. modulation index 2.3 means
-      0.7*modulation with index 2 and 0.3*modulation with index 3.
-
-effects:
-   reverb and controllable delay
-   phaser or Chebyshev filter
-
-continuous sounds:
-   fly
-   water/bubbles
-      when I accidentally did not scale filter frequency with sample rate,
-      the filter sound much like water bubbles.
-      I think a control curve consisting of some ramps will do the same.
-   hail, Geiger counter, pitch applied by comb filter
-      at a very high impulse rate the impulses itself
-      can generate an almost periodic signal
-
-
-Speech sounds improvements (tomatensalat)
-   use PSOLA for transposition
-   To this end divide signal into tonal part and residue (noise)
-   by a comb filter.
-   Maybe a non-linear comb filter may help,
-   that selects the center value from the filter window,
-   if the side values are similar
-   and returns zero, if the the side values differ too much.
-   Process the tonal part by PSOLA and
-   simply mix it with the non-tonal part on replay.
-
-Harmonizer-like:
-   We like to input an audio signal of speech
-   and a set of keys, and the speech is extended to chords
-   according to the pressed keys.
-   The lowest key is interpreted as base frequency of the input audio speech.
-   A PSOLA method transposes the audio input.
-
-Resonant filter controlled by keys
-   applied to an audio input signal
-   or an ordinary audio signal generated by other keys.
-   The splitting of keys however could be performed
-   by a MIDI event stream editor.
--}
-
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.Server.Packed.Instrument (
-   pingRelease,
-   pingStereoRelease,
-   pingStereoReleaseFM,
-   squareStereoReleaseFM,
-   bellStereoFM,
-   bellNoiseStereoFM,
-   tine,
-   tineStereo,
-   softString,
-   softStringFM,
-   tineStereoFM,
-   tineControlledFM,
-   fenderFM,
-   tineModulatorBankFM,
-   tineBankFM,
-   resonantFMSynth,
-   softStringDetuneFM,
-   softStringShapeFM, cosineStringStereoFM,
-   arcSineStringStereoFM, arcTriangleStringStereoFM,
-   arcSquareStringStereoFM, arcSawStringStereoFM,
-   fmStringStereoFM,
-   wind,
-   windPhaser,
-   filterSawStereoFM,
-   brass,
-   sampledSound,
-
-   -- * helper functions
-   stereoNoise,
-   frequencyFromBendModulation,
-   modulation,
-   piecewiseConstantVector,
-
-   -- * for testing
-   pingReleaseEnvelope,
-   adsr,
-   ) where
-
-import qualified Synthesizer.LLVM.Server.Parameter as ParamS
-import Synthesizer.LLVM.Server.CommonPacked
-import Synthesizer.LLVM.Server.Common
-import Synthesizer.LLVM.Server.Parameter
-         (Number(Number), Signal(Signal), Control(Control))
-
-import qualified Synthesizer.LLVM.Server.SampledSound as Sample
-import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
-import qualified Synthesizer.MIDI.PiecewiseConstant as PC
-import qualified Synthesizer.MIDI.EventList as Ev
-
-import Synthesizer.MIDI.Storable (chunkSizesFromLazyTime)
-
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Filter.Universal as UniFilterL
-import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
-import qualified Synthesizer.LLVM.Filter.Moog as MoogL
-import qualified Synthesizer.LLVM.MIDI as MIDIL
-import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS
-import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Simple.Signal as Sig
-import qualified Synthesizer.LLVM.Storable.Signal as SigStL
-import qualified Synthesizer.LLVM.Frame as Frame
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Wave as WaveL
-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($>), ($*))
-import Synthesizer.LLVM.CausalParameterized.Functional (($&), (&|&))
-
-import qualified LLVM.DSL.Parameter as Param
-import LLVM.DSL.Parameter (($#))
-
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Core as LLVM
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import qualified Synthesizer.Generic.Cut         as CutG
-import qualified Synthesizer.Storable.Signal      as SigSt
-import qualified Data.StorableVector.Lazy.Pattern as SVP
-import qualified Data.StorableVector.Lazy         as SVL
-
-import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilter
-
-import qualified Control.Monad.HT as M
-import Control.Arrow ((<<<), (^<<), (<<^), (&&&), (***), arr, first, second)
-import Control.Category (id)
-import Control.Applicative (liftA2, liftA3)
-import Data.Traversable (traverse)
-import qualified Data.Traversable as Trav
-
-import Data.Tuple.HT (fst3, snd3, thd3)
-
-import qualified Numeric.NonNegative.Chunky as NonNegChunky
-
-import qualified Algebra.Additive as Additive
-
-import NumericPrelude.Numeric (zero, one, round, (^?), (+), (-), (*))
-import Prelude hiding (Real, round, break, id, (+), (-), (*))
-
-
-
-frequencyControl :: (p -> PC.T Real) -> Param p (PC.T Real)
-frequencyControl param =
-   arr (\(SampleRate sampleRate, p) -> fmap (/sampleRate) $ param p)
-
-modulation ::
-   (p -> (PC.T (BM.T Real), Real)) -> Param p (PC.T (BM.T Real))
-modulation param =
-   arr (\(sr, p) ->
-      (\(fm,freq) -> transposeModulation sr freq fm) $ param p)
-
-newtype Modulation p = Modulation (Param p (PC.T (BM.T Real)))
-
-instance ParamS.Tuple (Modulation p) where
-   type Composed (Modulation p) = (PC.T (BM.T Real), Real)
-   type Source (Modulation p) = p
-   decompose sampleRate x =
-      Modulation $
-         liftA2 (\sr (fm,freq) -> transposeModulation sr freq fm) sampleRate x
-
-detuneModulation ::
-   (p -> (PC.T Real, PC.T (BM.T Real), Real)) ->
-   Param p (PC.T Real, PC.T (BM.T Real))
-detuneModulation param =
-   arr $ \(sr, p) ->
-      case param p of
-         (det,fm,freq) -> (det, transposeModulation sr freq fm)
-
-newtype
-   DetuneModulation p =
-      DetuneModulation (Param p (PC.T Real, PC.T (BM.T Real)))
-
-instance ParamS.Tuple (DetuneModulation p) where
-   type Composed (DetuneModulation p) = (PC.T Real, PC.T (BM.T Real), Real)
-   type Source (DetuneModulation p) = p
-   decompose sampleRate x =
-      DetuneModulation $
-         liftA2
-            (\sr (det,fm,freq) -> (det, transposeModulation sr freq fm))
-            sampleRate x
-
-
-
-frequencyFromBendModulation ::
-{-
-   (Storable a,
-    Tuple.Value a, ValueTuple a ~ (Value a)) =>
--}
-   Param p Real ->
-   Param p (PC.T (BM.T Real)) ->
-   SigP p VectorValue
-frequencyFromBendModulation speed fmFreq =
-   MIDIL.frequencyFromBendModulationPacked speed
-      $* piecewiseConstant fmFreq
-
-stereoFrequenciesFromDetuneBendModulation ::
-   Param p Real ->
-   Param p (PC.T Real, PC.T (BM.T Real)) ->
-   SigP p (Stereo.T VectorValue)
-stereoFrequenciesFromDetuneBendModulation speed detFmFreq =
-   (CausalP.envelopeStereo
-      $< frequencyFromBendModulation speed
-           (fmap (\(_det,fm) -> (fm)) detFmFreq))
-   <<<
-   liftA2 Stereo.cons (one + id) (one - id)
-   $* piecewiseConstantVector
-         (fmap (\(det,_fm) -> det) detFmFreq)
-
-piecewiseConstantVector ::
-   Param.T p (PC.T Real) -> SigP.T p VectorValue
-{-
-   (Storable a,
-    Tuple.Value a, Tuple.ValueOf a ~ al,
-    Memory.C al am,
-    LLVM.IsSized am as) =>
-   Param.T p (PC.T a) -> SigP.T p (Serial.Value n al)
--}
-piecewiseConstantVector =
-   piecewiseConstant . fmap (fmap (Serial.replicate))
-
-
-pingReleaseEnvelope ::
-   IO (Real -> Real ->
-       SigSt.ChunkSize ->
-       SampleRate Real -> Real -> Ev.LazyTime -> SigSt.T Vector)
-pingReleaseEnvelope =
-   liftA2
-      (\pressed release decay rel vcsize sr vel dur ->
-         SigStL.continuePacked
-            (pressed (chunkSizesFromLazyTime dur) (sr, (decay,vel)))
-            (\x -> release vcsize (sr, (rel,x))))
-      (SigP.runChunkyPattern $
-       let decay = time fst
-           velocity = number snd
-       in  SigPS.exponential2 decay
-              (amplitudeFromVelocity ^<< velocity))
-      (SigP.runChunky $
-       let releaseTime = vectorTime fst * 5
-           releaseHL = time fst
-           amplitude = number snd
-       in  CausalP.take (round ^<< releaseTime) $*
-           SigPS.exponential2 releaseHL amplitude)
-
-pingRelease ::
-   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real Vector)
-pingRelease =
-   liftA2
-      (\osc env dec rel vcsize sr vel freq dur ->
-         osc (sr,freq) (env dec rel vcsize sr vel dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency id
-          in  CausalP.envelope $>
-              SigPS.osciSimple WaveL.saw zero freq))
-      pingReleaseEnvelope
-
-pingStereoRelease ::
-   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Vector))
-pingStereoRelease =
-   liftA2
-      (\osc env dec rel vcsize sr vel freq dur ->
-         osc (sr,freq) (env dec rel vcsize sr vel dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency id
-          in  CausalP.envelopeStereo $>
-              liftA2 Stereo.cons
-                 (SigPS.osciSimple WaveL.saw zero (0.999*freq))
-                 (SigPS.osciSimple WaveL.saw zero (1.001*freq))))
-      pingReleaseEnvelope
-
-pingStereoReleaseFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       PC.T Real ->
-       Real -> Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-pingStereoReleaseFM =
-   liftA2
-      (\osc env dec rel detune shape phase phaseDecay vcsize fm sr vel freq dur ->
-         osc
-            (sr, ((phase, phaseDecay), shape, (detune,fm,freq)))
-            (env dec rel vcsize sr vel dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-         \((Number phase, ParamS.Time decay),
-            Control shape, DetuneModulation fm) ->
-              CausalP.envelopeStereo $>
-              ((CausalP.stereoFromMonoControlled
-                  (CausalPS.shapeModOsci WaveL.rationalApproxSine1)
-                    $< piecewiseConstantVector shape)
-                  <<^ Stereo.interleave
-                $< (liftA2 Stereo.cons id (Additive.negate id)
-                     $* SigPS.exponential2 decay phase)
-                $* stereoFrequenciesFromDetuneBendModulation (frequencyConst 10) fm))
-      pingReleaseEnvelope
-
-{- |
-Square like wave constructed as difference
-of two phase shifted sawtooth like oscillations.
--}
-squareStereoReleaseFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-squareStereoReleaseFM =
-   liftA2
-      (\osc env dec rel detune shape phase vcsize fm sr vel freq dur ->
-         osc
-            (sr, ((phase, shape), (detune,fm,freq)))
-            (env dec rel vcsize sr vel dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $ \((Control phs, Control shp), DetuneModulation fm) ->
-         (let chanOsci ::
-                 CausalP p
-                    ((VectorValue, VectorValue), VectorValue)
-                    VectorValue
-              chanOsci =
-                 ((CausalPS.shapeModOsci WaveL.rationalApproxSine1
-                   <<<
-                   second (first (Additive.negate id)))
-                  -
-                   CausalPS.shapeModOsci WaveL.rationalApproxSine1)
-                 <<^
-                 (\((p,s),f) -> (s,(p,f)))
-          in  CausalP.envelopeStereo $>
-              ((CausalP.stereoFromMonoControlled chanOsci
-                   $< SigP.zip
-                         (piecewiseConstantVector phs)
-                         (piecewiseConstantVector shp))
-                $* stereoFrequenciesFromDetuneBendModulation (frequencyConst 10) fm)))
-      pingReleaseEnvelope
-
-
-type Triple a = (a, a, a)
-
-bellStereoFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-bellStereoFM =
-   liftA2
-      (\osc env dec rel detune vcsize fm sr vel freq dur ->
-         osc (sr, ((detune, fm, freq), vel,
-                   (env (dec/4) rel vcsize sr vel dur,
-                    env (dec/7) rel vcsize sr vel dur)))
-             (env dec rel vcsize sr vel dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-       \(DetuneModulation fm, Number vel, (Signal env4, Signal env7)) ->
-         (let osci ::
-                 (Triple VectorValue -> VectorValue) ->
-                 Param.T p Real ->
-                 Param.T p Real ->
-                 CausalP.T p
-                    (Triple VectorValue, Stereo.T VectorValue)
-                    (Stereo.T VectorValue)
-              osci sel v d =
-                 CausalP.envelopeStereo
-                 <<<
-                 (arr sel ***
-                    (CausalPS.amplifyStereo v
-                     <<<
-                     CausalP.stereoFromMono
-                        (CausalPS.osciSimple WaveL.approxSine4 $< zero)
-                     <<<
-                     CausalPS.amplifyStereo d))
-          in  sumNested
-                 [osci fst3  0.6              1,
-                  osci snd3 (0.02 *  50^?vel) 4,
-                  osci thd3 (0.02 * 100^?vel) 7]
-              <<<
-              CausalP.feedSnd (stereoFrequenciesFromDetuneBendModulation (frequencyConst 5) fm)
-              <<<
-              arr (\(e1,(e4,e7)) -> (e1,e4,e7))
-               $> {-
-                  Be careful, those storable vectors shorten the whole sound
-                  if they have shorter release than the main envelope.
-                  -}
-                  SigP.zip
-                     (SigP.fromStorableVectorLazy env4)
-                     (SigP.fromStorableVectorLazy env7)))
-      pingReleaseEnvelope
-
-bellNoiseStereoFM ::
-   IO (Real -> Real ->
-       PC.T Real -> PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-bellNoiseStereoFM =
-   liftA2
-      (\osc env dec rel noiseAmp noiseReson vcsize fm sr vel freq dur ->
-         osc (sr,
-              ((fm, freq),
-               (noiseAmp,noiseReson),
-               (vel,
-                env (dec/4) rel vcsize sr vel dur,
-                env (dec/7) rel vcsize sr vel dur)))
-             (env dec rel vcsize sr vel dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-       \(Modulation fm,
-         (Control noiseAmp, Control noiseReson),
-         (Number vel, Signal env4, Signal env7)) ->
-         (let osci ::
-                 (Triple VectorValue -> VectorValue) ->
-                 Param.T p Real ->
-                 Param.T p Real ->
-                 CausalP.T p
-                    (Triple VectorValue, VectorValue)
-                    VectorValue
-              osci sel v d =
-                 CausalP.envelope
-                 <<<
-                 (arr sel ***
-                    (CausalPS.amplify v
-                     <<<
-                     (CausalPS.osciSimple WaveL.approxSine4 $< zero)
-                     <<<
-                     CausalPS.amplify d))
-
-              noise ::
-                 (p ~
-                     ((PC.T (BM.T Real), Real),
-                      (PC.T Real, PC.T Real),
-                      (Real, SigSt.T Vector, SigSt.T Vector))) =>
-                 (Triple VectorValue -> VectorValue) ->
-                 Param p Real ->
-                 CausalP p (Triple VectorValue, VectorValue) VectorValue
-              noise sel d =
-                 (CausalP.envelope $< piecewiseConstantVector noiseAmp)
-                 <<<
-                 CausalP.envelope
-                 <<<
-                 (arr sel ***
-                    ({- UniFilter.lowpass
-                        ^<< -}
-                     (CtrlPS.process
-                        $> SigPS.noise 12 (noiseReference 20000))
-                     <<<
-{-
-                     (CausalP.quantizeLift
-                        $# (128 / fromIntegral vectorSize :: Real))
-                           (CausalP.zipWithSimple UniFilterL.parameter)
--}
-                     (CausalP.quantizeLift
-                        $# (128 / fromIntegral vectorSize :: Real))
-                           (CausalP.zipWithSimple (MoogL.parameter TypeNum.d8))
-                     <<<
-                     CausalP.feedFst (piecewiseConstant noiseReson)
-                     <<<
-                     CausalP.mapSimple Serial.subsample
-                     <<<
-                     CausalPS.amplify d))
-          in  liftA2 Stereo.cons
-                 (sumNested
-                    [osci fst3  0.6              (1*0.999),
-                     osci snd3 (0.02 *  50^?vel) (4*0.999),
-                     osci thd3 (0.02 * 100^?vel) (7*0.999),
-                     noise fst3 0.999])
-                 (sumNested
-                    [osci fst3  0.6              (1*1.001),
-                     osci snd3 (0.02 *  50^?vel) (4*1.001),
-                     osci thd3 (0.02 * 100^?vel) (7*1.001),
-                     noise fst3 1.001])
-              <<<
-              CausalP.feedSnd (frequencyFromBendModulation (frequencyConst 5) fm)
-              <<<
-              arr (\(e1,(e4,e7)) -> (e1,e4,e7))
-               $> {-
-                  Be careful, those storable vectors shorten the whole sound
-                  if they have shorter release than the main envelope.
-                  -}
-                  SigP.zip
-                     (SigP.fromStorableVectorLazy env4)
-                     (SigP.fromStorableVectorLazy env7)))
-      pingReleaseEnvelope
-
-
-tine :: IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real Vector)
-tine =
-   liftA2
-      (\osc env dec rel vcsize sr vel freq dur ->
-         osc (sr, (vel,freq)) (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency snd
-              vel  = number fst
-          in  CausalP.envelope $>
-                 (CausalPS.osciSimple WaveL.approxSine2
-                    $> SigPS.constant freq
-                    $* (CausalP.envelope
-                          $< SigPS.exponential2 (timeConst 1) (vel+1)
-                          $* SigPS.osciSimple WaveL.approxSine2 zero
-                                (2*freq)))))
-      pingReleaseEnvelope
-
-tineStereo ::
-   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Vector))
-tineStereo =
-   liftA2
-      (\osc env dec rel vcsize sr vel freq dur ->
-         osc (sr, (vel,freq)) (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency snd
-              vel  = number fst
-              chanOsci d =
-                 CausalPS.osciSimple WaveL.approxSine2
-                    $> SigPS.constant (freq*d)
-          in  CausalP.envelopeStereo $>
-                 (liftA2 Stereo.cons
-                    (chanOsci 0.995) (chanOsci 1.005)
-                  $* SigP.envelope
-                        (SigPS.exponential2 (timeConst 1) (vel+1))
-                        (SigPS.osciSimple WaveL.approxSine2 zero
-                           (2*freq)))))
-      pingReleaseEnvelope
-
-
-softStringReleaseEnvelope ::
-   IO (Real -> SampleRate Real -> Real -> Ev.LazyTime -> SigSt.T Vector)
-softStringReleaseEnvelope =
-   liftA2
-      (\rev env attackTime sr vel dur ->
-         let attackTimeVector =
-                round (attackTime * vectorRate sr)
-             {-
-             release <- take attackTime beginning
-             would yield a space leak, thus we first split 'beginning'
-             and then concatenate it again
-             -}
-             {-
-             We can not easily generate attack and sustain separately,
-             because we want to use the chunk structure implied by 'dur'.
-             -}
-             (attack, sustain) =
-                SigSt.splitAt attackTimeVector $
-                env (chunkSizesFromLazyTime dur)
-                    (sr, (amplitudeFromVelocity vel, attackTimeVector))
-             release = rev attack
-         in  attack `SigSt.append` sustain `SigSt.append` release)
-      SigStL.makeReversePacked
-      (let amp = number fst
-           attackTimeVector = parameter snd
-       in  SigP.runChunkyPattern $
-           flip SigP.append (SigPS.constant amp) $
-           (CausalPS.amplify amp <<<
-            CausalP.take attackTimeVector
-            $* SigPS.parabolaFadeInInf
-                  (fmap (fromIntegral . (vectorSize*)) attackTimeVector)))
-
-softString :: IO (Instrument Real (Stereo.T Vector))
-softString =
-   liftA2
-      (\osc env sr vel freq dur ->
-         osc (sr, freq) (env 1 sr vel dur))
-      (let freq = frequency id
-           osci d = SigPS.osciSimple WaveL.saw zero (d * freq)
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $>
-              (liftA2 Stereo.cons
-                 (osci 1.005 + osci 0.998)
-                 (osci 1.002 + osci 0.995))))
-      softStringReleaseEnvelope
-
-
-softStringFM :: IO (PC.T (BM.T Real) -> Instrument Real (Stereo.T Vector))
-softStringFM =
-   liftA2
-      (\osc env fm sr vel freq dur ->
-         osc (sr, (fm,freq)) (env 1 sr vel dur))
-      (let fm = modulation id
-           osci ::
-              Param.T fm Real ->
-              CausalP.T fm VectorValue VectorValue
-           osci d =
-              (CausalPS.osciSimple WaveL.saw $< zero) <<<
-              CausalPS.amplify d
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $>
-              (liftA2 Stereo.cons
-                  (osci 1.005 + osci 0.998)
-                  (osci 1.002 + osci 0.995)
-               $* frequencyFromBendModulation (frequencyConst 5) fm)))
-      softStringReleaseEnvelope
-
-
-tineStereoFM ::
-   IO (Real -> Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-tineStereoFM =
-   liftA2
-      (\osc env dec rel vcsize fm sr vel freq dur ->
-         osc (sr, (vel,(fm,freq))) (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky
-         (let vel  = number fst
-              fm   = modulation snd
-              chanOsci d =
-                 CausalPS.osciSimple WaveL.approxSine2
-                    <<< second (CausalPS.amplify d)
-          in  CausalP.envelopeStereo $>
-                 (liftA2 Stereo.cons
-                     (chanOsci 0.995) (chanOsci 1.005)
-                  <<<
-                  (((CausalP.envelope
-                       $< SigPS.exponential2 (timeConst 1) (vel+1))
-                     <<< (CausalPS.osciSimple WaveL.approxSine2 $< zero)
-                     <<< CausalPS.amplify 2)
-                   &&& id)
-                  $* frequencyFromBendModulation (frequencyConst 5) fm)))
-      pingReleaseEnvelope
-
-
-_tineControlledProc, tineControlledFnProc ::
-   Param p (PC.T Real) ->
-   Param p (PC.T Real) ->
-   Param p Real ->
-   CausalP p
-      (Stereo.T VectorValue)
-      (Stereo.T VectorValue)
-_tineControlledProc index depth vel =
-   CausalP.stereoFromMono
-      (CausalPS.osciSimple WaveL.approxSine2)
-   <<<
-   Stereo.interleave
-   ^<<
-   ((CausalP.envelopeStereo
-       $< SigP.envelope
-             (piecewiseConstantVector depth)
-             (SigPS.exponential2 (timeConst 1) (vel+1)))
-    <<<
-    CausalP.stereoFromMono
-       (CausalPS.osciSimple WaveL.approxSine2 $< zero)
-    <<<
-    (CausalP.envelopeStereo
-       $< piecewiseConstantVector index))
-            &&& id
-
-tineControlledFnProc index depth vel =
-   F.withGuidedArgs F.atom $ \freq ->
-      CausalP.stereoFromMono
-         (CausalPS.osciSimple WaveL.approxSine2)
-      $&
-      liftA2 (liftA2 (,))
-         ((CausalP.envelopeStereo
-             $< SigP.envelope
-                   (piecewiseConstantVector depth)
-                   (SigPS.exponential2 (timeConst 1) (vel+1)))
-          <<<
-          CausalP.stereoFromMono
-             (CausalPS.osciSimple WaveL.approxSine2 $< zero)
-          <<<
-          (CausalP.envelopeStereo
-             $< piecewiseConstantVector index)
-          $&
-          freq)
-         freq
-
-tineControlledFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       PC.T Real -> PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-tineControlledFM =
-   liftA2
-      (\osc env dec rel detune index depth vcsize fm sr vel freq dur ->
-         osc
-            (sr, ((index, depth), vel, (detune,fm,freq)))
-            (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-       \((Control index, Control depth), Number vel, DetuneModulation fm) ->
-         CausalP.envelopeStereo $>
-            (tineControlledFnProc index depth vel $*
-             stereoFrequenciesFromDetuneBendModulation (frequencyConst 5) fm))
-      pingReleaseEnvelope
-
-
-fenderProc ::
-   Param p (PC.T Real) ->
-   Param p (PC.T Real) ->
-   Param p (PC.T Real) ->
-   Param p Real ->
-   CausalP p
-      (Stereo.T VectorValue)
-      (Stereo.T VectorValue)
-fenderProc fade index depth vel =
-   F.withGuidedArgs F.atom $ \stereoFreq ->
-       let {-
-           channel_n_1 ::
-              FuncP p VectorValue VectorValue ->
-              FuncP p VectorValue VectorValue
-           -}
-           channel_n_1 freq =
-              CausalPS.osciSimple WaveL.approxSine2
-              $&
-              ((CausalP.envelope
-                  $< SigP.envelope
-                        (piecewiseConstantVector depth)
-                        (SigPS.exponential2 (timeConst 1) (vel+1)))
-               <<<
-               (CausalPS.osciSimple WaveL.approxSine2 $< zero)
-               <<<
-               (CausalP.envelope
-                  $< piecewiseConstantVector index)
-               $&
-               freq)
-              &|&
-              freq
-           {-
-           channel_1_2 ::
-              FuncP p VectorValue VectorValue ->
-              FuncP p VectorValue VectorValue
-           -}
-           channel_1_2 freq =
-              CausalPS.osciSimple WaveL.approxSine2
-              $&
-              ((CausalP.envelope
-                  $< SigP.envelope
-                        (piecewiseConstantVector depth)
-                        (SigPS.exponential2 (timeConst 1) (vel+1)))
-               <<<
-               (CausalPS.osciSimple WaveL.approxSine2 $< zero)
-               $&
-               freq)
-              &|&
-              (CausalPS.amplify 2 $& freq)
-       in  (CausalP.stereoFromMonoControlled
-              (fadeProcess
-                 (F.compile $ channel_n_1 $ F.lift id)
-                 (F.compile $ channel_1_2 $ F.lift id))
-              $< piecewiseConstantVector fade)
-           $&
-           stereoFreq
-
-fenderFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       PC.T Real -> PC.T Real -> PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-fenderFM =
-   liftA2
-      (\osc env dec rel detune index depth fade vcsize fm sr vel freq dur ->
-         osc
-            (sr, (((index, depth), fade), vel, (detune,fm,freq)))
-            (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-       \(((Control index, Control depth), Control fade),
-            Number vel, DetuneModulation fm) ->
-         CausalP.envelopeStereo $>
-            (fenderProc fade index depth vel $*
-             stereoFrequenciesFromDetuneBendModulation (frequencyConst 5) fm))
-      pingReleaseEnvelope
-
-
-fmModulator ::
-   Param p Real ->
-   Param p Real ->
-   Param p (PC.T Real) ->
-   CausalP p
-      (Stereo.T VectorValue)
-      (Stereo.T VectorValue)
-fmModulator vel n depth =
-   (CausalP.envelopeStereo
-      $< SigP.envelope
-            (piecewiseConstantVector depth)
-            (SigPS.exponential2 (timeConst 1) (vel+1)))
-   <<<
-   CausalP.stereoFromMono
-      (CausalPS.osciSimple WaveL.approxSine2 $< zero)
-   <<<
-   CausalPS.amplifyStereo n
-
-tineModulatorBankFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       PC.T Real -> PC.T Real -> PC.T Real -> PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-tineModulatorBankFM =
-   liftA2
-      (\osc env
-            dec rel detune
-            depth1 depth2 depth3 depth4
-            vcsize fm sr vel freq dur ->
-         osc
-            (sr, ((depth1,(depth2,(depth3,(depth4)))), vel, (detune,fm,freq)))
-            (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-       \((Control depth1, (Control depth2, (Control depth3, Control depth4))),
-            Number vel, DetuneModulation fm) ->
-              (CausalP.envelopeStereo $>
-                 (CausalP.stereoFromMono
-                     (CausalPS.osciSimple WaveL.approxSine2)
-                  <<<
-                  Stereo.interleave
-                  ^<<
-                  sumNested
-                     [fmModulator vel 1 depth1,
-                      fmModulator vel 2 depth2,
-                      fmModulator vel 3 depth3,
-                      fmModulator vel 4 depth4]
-                    &&& id
-                  $*
-                  stereoFrequenciesFromDetuneBendModulation (frequencyConst 5) fm)))
-      pingReleaseEnvelope
-
-tineBankFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       PC.T Real -> PC.T Real -> PC.T Real -> PC.T Real ->
-       PC.T Real -> PC.T Real -> PC.T Real -> PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-tineBankFM =
-   liftA2
-      (\osc env
-            dec rel detune
-            depth1 depth2 depth3 depth4
-            partial1 partial2 partial3 partial4
-            vcsize fm sr vel freq dur ->
-         osc
-            (sr,
-             ((depth1,(depth2,(depth3,(depth4)))),
-              (partial1,(partial2,(partial3,(partial4)))),
-              (vel, (detune,fm,freq))))
-            (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-         \((Control depth1, (Control depth2, (Control depth3, Control depth4))),
-           (Control partial1,(Control  partial2, (Control partial3, Control partial4))),
-           (Number vel, DetuneModulation fm)) ->
-
-         (let partial ::
-                 VectorValue -> Int -> VectorValue ->
-                 LLVM.CodeGenFunction r VectorValue
-              partial amp n t =
-                 A.mul amp =<<
-                 WaveL.partial WaveL.approxSine2 n t
-          in  CausalP.envelopeStereo $>
-                 (CausalP.stereoFromMono
-                     (CausalPS.shapeModOsci
-                         (\(p1,(p2,(p3,p4))) t -> do
-                             y1 <- A.mul p1 =<< WaveL.approxSine2 t
-                             y2 <- partial p2 2 t
-                             y3 <- partial p3 3 t
-                             y4 <- partial p4 4 t
-                             A.add y1 =<< A.add y2 =<< A.add y3 y4)
-                        $<
-                           (SigP.zip (piecewiseConstantVector partial1) $
-                            SigP.zip (piecewiseConstantVector partial2) $
-                            SigP.zip (piecewiseConstantVector partial3)
-                                     (piecewiseConstantVector partial4)))
-                  <<<
-                  Stereo.interleave
-                  ^<<
-                  sumNested
-                     [fmModulator vel 1 depth1,
-                      fmModulator vel 2 depth2,
-                      fmModulator vel 3 depth3,
-                      fmModulator vel 4 depth4]
-                    &&& id
-                  $*
-                  stereoFrequenciesFromDetuneBendModulation (frequencyConst 5) fm)))
-      pingReleaseEnvelope
-
-
-{- |
-FM synthesis where the modulator is a resonantly filtered sawtooth.
-This way we get a sinus-like modulator where the sine frequency
-(that is, something like the modulation index) can be controlled continously.
--}
-resonantFMSynthProc ::
-   Param p (PC.T Real) ->
-   Param p (PC.T Real) ->
-   Param p (PC.T Real) ->
-   Param p Real ->
-   CausalP p
-      (Stereo.T VectorValue)
-      (Stereo.T VectorValue)
-resonantFMSynthProc reson index depth vel =
-   F.withGuidedArgs (Stereo.cons F.atom F.atom) $ \stereoFreq ->
-       let -- chan :: FuncP p inp VectorValue -> FuncP p inp VectorValue
-           chan freq =
-              CausalPS.osciSimple WaveL.approxSine2
-              $&
-              ((CausalP.envelope
-                  $< SigP.envelope
-                        (piecewiseConstantVector depth)
-                        (SigPS.exponential2 (timeConst 1) (vel+1)))
-               <<<
-               UniFilter.lowpass
-               ^<<
-               CtrlPS.process
-               $&
-               (CausalP.zipWithSimple UniFilterL.parameter
-                   <<<
-                   CausalP.feedFst (piecewiseConstant reson)
-                   <<<
-                   (CausalP.envelope $< piecewiseConstant index)
-                   <<<
-                   CausalP.mapSimple Serial.subsample
-                   $&
-                   freq)
-               &|&
-               ((CausalPS.osciSimple WaveL.saw $< zero)
-                $&
-                freq))
-              &|&
-              freq
-       in  Trav.traverse chan stereoFreq
-
-resonantFMSynth ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       PC.T Real -> PC.T Real -> PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-resonantFMSynth =
-   liftA2
-      (\osc env dec rel detune reson index depth vcsize fm sr vel freq dur ->
-         osc
-            (sr, ((reson, index, depth), vel, (detune,fm,freq)))
-            (env dec rel vcsize sr 0 dur))
-      (CausalP.runStorableChunky $
-       ParamS.withTuple2 $
-       \((Control reson, Control index, Control depth),
-         Number vel, DetuneModulation fm) ->
-            CausalP.envelopeStereo $>
-               (resonantFMSynthProc reson index depth vel $*
-                stereoFrequenciesFromDetuneBendModulation (frequencyConst 5) fm))
-      pingReleaseEnvelope
-
-
-phaserOsci ::
-   (Param.T p Real -> CausalP.T p a VectorValue) ->
-   CausalP.T p a (Stereo.T VectorValue)
-phaserOsci osci =
-   CausalPS.amplifyStereo 0.25
-   <<<
-   liftA2 Stereo.cons
-      (sumNested $ map osci [1.0, -0.4, 0.5, -0.7])
-      (sumNested $ map osci [0.4, -1.0, 0.7, -0.5])
-
-
-softStringDetuneFM ::
-   IO (Real ->
-       PC.T Real ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-softStringDetuneFM =
-   liftA2
-      (\osc env att det fm sr vel freq dur ->
-         osc (sr, (det, (fm,freq))) (env att sr vel dur))
-      (let det = control fst
-           fm  = modulation snd
-           osci ::
-              Param.T (det,fm) Real ->
-              CausalP.T (det,fm)
-                 (VectorValue, VectorValue)
-                 VectorValue
-           osci d =
-              (CausalPS.osciSimple WaveL.saw $< zero)
-              <<<
-              CausalP.envelope
-              <<<
-              first (one + CausalPS.amplify d)
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $>
-              (phaserOsci osci
-               <<<
-               CausalP.feedFst (piecewiseConstantVector det)
-               $* frequencyFromBendModulation (frequencyConst 5) fm)))
-      softStringReleaseEnvelope
-
-{-
-We might decouple the frequency of the enveloped tone
-from the frequency of the envelope,
-in order to get something like formants.
--}
-softStringShapeFM, cosineStringStereoFM,
-  arcSineStringStereoFM, arcTriangleStringStereoFM,
-  arcSquareStringStereoFM, arcSawStringStereoFM ::
-   IO (Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-softStringShapeFM =
-   softStringShapeCore WaveL.rationalApproxSine1
-cosineStringStereoFM =
-   softStringShapeCore
-      (\k p -> WaveL.approxSine2 =<< WaveL.replicate k p)
-arcSawStringStereoFM = arcStringStereoFM WaveL.saw
-arcSineStringStereoFM = arcStringStereoFM WaveL.approxSine2
-arcSquareStringStereoFM = arcStringStereoFM WaveL.square
-arcTriangleStringStereoFM = arcStringStereoFM WaveL.triangle
-
-arcStringStereoFM ::
-   (forall r.
-    VectorValue ->
-    LLVM.CodeGenFunction r VectorValue) ->
-   IO (Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-arcStringStereoFM wave =
-   softStringShapeCore
-      (\k p ->
-         M.liftJoin2 Frame.amplifyMono
-            (WaveL.approxSine4 =<< WaveL.halfEnvelope p)
-            (wave =<< WaveL.replicate k p))
-
-softStringShapeCore ::
-   (forall r.
-    VectorValue ->
-    VectorValue ->
-    LLVM.CodeGenFunction r VectorValue) ->
-   IO (Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-softStringShapeCore wave =
-   liftA2
-      (\osc env att det dist fm sr vel freq dur ->
-         osc (sr, ((det, dist), (fm,freq))) (env att sr vel dur))
-      (let det  = control (fst.fst)
-           dist = control (snd.fst)
-           fm   = modulation snd
-           osci ::
-              Param.T (mod,fm) Real ->
-              CausalP.T (mod,fm)
-                 (VectorValue,
-                       {- wave shape parameter -}
-                  (VectorValue, VectorValue)
-                       {- detune, frequency modulation -})
-                 VectorValue
-           osci d =
-              CausalPS.shapeModOsci wave
-              <<<
-              second
-                 (CausalP.feedFst zero
-                  <<<
-                  CausalP.envelope
-                  <<<
-                  first (one + CausalPS.amplify d))
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $>
-              (phaserOsci osci
-               $< piecewiseConstantVector dist
-               $< piecewiseConstantVector det
-               $* frequencyFromBendModulation (frequencyConst 5) fm)))
-      softStringReleaseEnvelope
-
-fmStringStereoFM ::
-   IO (Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-fmStringStereoFM =
-   liftA2
-      (\osc env att det depth dist fm sr vel freq dur ->
-         osc (sr, ((det, depth, dist), (fm, freq))) (env att sr vel dur))
-      (let det   = control (fst3.fst)
-           depth = control (snd3.fst)
-           dist  = control (thd3.fst)
-           fm  = modulation snd
-           osci ::
-              Param.T (mod,fm) Real ->
-              CausalP.T (mod,fm)
-                 ((VectorValue, VectorValue)
-                       {- phase modulation depth, modulator distortion -},
-                  (VectorValue, VectorValue)
-                       {- detune, frequency modulation -})
-                 VectorValue
-           osci d =
-              CausalPS.osciSimple WaveL.approxSine2
-              <<<
-              (CausalP.envelope
-               <<<
-               second
-                  (CausalPS.shapeModOsci WaveL.rationalApproxSine1
-                     <<< second (CausalP.feedFst zero))
-               <<^
-               (\((dp, ds), f) -> (dp, (ds, f))))
-               &&& arr snd
-              <<<
-              second
-                 (CausalP.envelope <<<
-                  first (one + CausalPS.amplify d))
-       in  CausalP.runStorableChunky
-              (CausalP.envelopeStereo <<<
-                 (id &&&
-                  (phaserOsci osci
-                   <<<
-                   CausalP.feedSnd
-                      (SigP.zip
-                         (piecewiseConstantVector det)
-                         (frequencyFromBendModulation (frequencyConst 5) fm))
-                   <<<
-                   CausalP.feedSnd (piecewiseConstantVector dist)
-                   <<<
-                   (CausalP.envelope
-                       $< piecewiseConstantVector depth)))))
-      softStringReleaseEnvelope
-
-
-stereoNoise :: SigP p (Stereo.T VectorValue)
-stereoNoise =
-   traverse
-      (\uid -> SigPS.noise uid (noiseReference 20000))
-      (Stereo.cons 13 14)
-
-windCore ::
-   Param p (PC.T Real) ->
-   Param p (PC.T (BM.T Real)) ->
-   SigP p (Stereo.T VectorValue)
-windCore reson fm =
-   CausalP.stereoFromMonoControlled CtrlPS.process
-    $< Sig.zipWith
-          (MoogL.parameter TypeNum.d8)
-          (piecewiseConstant reson)
-          (Sig.map Serial.subsample
-             (frequencyFromBendModulation (frequencyConst 0.2) fm))
-    $* stereoNoise
-
-wind ::
-   IO (Real ->
-       PC.T Real ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-wind =
-   liftA2
-      (\osc env att reson fm sr vel freq dur ->
-         osc (sr, (reson, (fm,freq))) (env att sr vel dur))
-      (let reson = control fst
-           fm = modulation snd
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $> windCore reson fm))
-      softStringReleaseEnvelope
-
-
-fadeProcess ::
-   (A.PseudoRing v, A.IntegerConstant v) =>
-   CausalP.T p a v ->
-   CausalP.T p a v ->
-   CausalP.T p (v, a) v
-fadeProcess proc0 proc1 =
-   let k = arr fst
-       a0 = proc0 <<^ snd
-       a1 = proc1 <<^ snd
-   in  (one-k)*a0 + k*a1
-
-
-windPhaser ::
-   IO (Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T Real ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-windPhaser =
-   liftA2
-      (\osc env att phaserMix phaserFreq reson fm sr vel freq dur ->
-         osc (sr, ((phaserMix,phaserFreq), reson, (fm,freq))) (env att sr vel dur))
-      (let phaserMix = control (fst.fst3)
-           phaserFreq = frequencyControl (snd.fst3)
-           reson = control snd3
-           fm = modulation thd3
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $>
-              ((CausalP.stereoFromMonoControlled
-                   (fadeProcess (arr snd) CtrlPS.process
-                    <<<
-                    first (CausalP.mapSimple Serial.upsample)
-                    <<^
-                    (\((k,p),x) -> (k,(p,x))))
-                  $< SigP.zip
-                        (piecewiseConstant phaserMix)
-                        (piecewiseConstant
-                           (fmap (Allpass.flangerParameterPlain TypeNum.d8)
-                               ^<< phaserFreq)))
-               $*
-               windCore reson fm)))
-      softStringReleaseEnvelope
-
-
-filterSawStereoFM ::
-   IO (Real -> Real ->
-       PC.T Real ->
-       Real -> Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-filterSawStereoFM =
-   liftA2
-      (\osc env dec rel detune bright brightDecay vcsize fm sr vel freq dur ->
-         osc
-            (sr, ((bright, brightDecay), (detune,fm,freq)))
-            (env dec rel vcsize sr vel dur))
-      (CausalP.runStorableChunky
-         (let bright    = frequency (fst.fst)
-              brightDec = time (snd.fst)
-              fm = detuneModulation snd
-          in  CausalP.envelopeStereo $>
-              (CausalP.stereoFromMono
-                  (UniFilter.lowpass
-                   ^<<
-                   (CtrlPS.processCtrlRate $# (100::Real))
-                      (\k -> Sig.map
-                          (UniFilterL.parameter (LLVM.valueOf 10))
-                          {- bound control in order to avoid too low resonant frequency,
-                             which makes the filter instable -}
-                          (SigP.exponentialBounded2
-                              (frequencyConst 100)
-                              (brightDec/k)
-                              (bright)))
-                   <<<
-                   CausalPS.osciSimple WaveL.saw $< zero)
-               $* stereoFrequenciesFromDetuneBendModulation (frequencyConst 10) fm)))
-      pingReleaseEnvelope
-
-
-{- |
-The ADSR curve is composed from three parts:
-Attack, Decay(+Sustain), Release.
-Attack starts when the key is pressed
-and lasts attackTime seconds
-where it reaches height attackPeak*amplitudeOfVelocity.
-It should be attackPeak>1 because in the following phase
-we want to approach 1 from above.
-Say the curve would approach the limit value L
-if it would continue after the end of the attack phase,
-the slope is determined by the halfLife with respect to this upper bound.
-That is, attackHalfLife is the time in seconds where the attack curve
-reaches or would reach L/2.
-After Attack the Decay part starts at the same level
-and decays to amplitudeOfVelocity.
-The slope is again a halfLife,
-that is, decayHalfLife is the time where the curve
-drops from attackPeak*amplitudeOfVelocity to (attackPeak+1)/2*amplitudeOfVelocity.
-This phase lasts as long as the key is pressed.
-If the key is released the curve decays with half life releaseHalfLife.
--}
-{-
-1 - 2^(-attackTime/attackHalfLife) = peak
--}
-adsr ::
-   IO (Real -> Real -> Real ->
-       Real -> Real ->
-       SigSt.ChunkSize ->
-       SampleRate Real -> Real -> Ev.LazyTime -> SigSt.T Vector)
-adsr =
-   liftA3
-      (\attack decay release
-           attackTime attackPeak attackHalfLife
-           decayHalfLife releaseHalfLife vcsize sr vel dur ->
-         let amp = amplitudeFromVelocity vel
-             (attackDur, decayDur) =
-                CutG.splitAt (round (attackTime * vectorRate sr)) dur
-         in  SigStL.continuePacked
-                (attack (chunkSizesFromLazyTime attackDur)
-                    (sr,
-                     (attackHalfLife,
-                      attackPeak * amp / (1 - 2^?(-attackTime/attackHalfLife))))
-                 `SigSt.append`
-                 decay (chunkSizesFromLazyTime decayDur)
-                    (sr,
-                     (decayHalfLife,
-                      ((attackPeak-1)*amp, amp))))
-                (\x -> release vcsize (sr,(releaseHalfLife,x))))
-      (SigP.runChunkyPattern $
-       let halfLife  = time fst
-           amplitude = number snd
-       in  SigPS.constant amplitude -
-           SigPS.exponential2 halfLife amplitude)
-      (SigP.runChunkyPattern $
-       let halfLife   = time fst
-           amplitude  = number (fst.snd)
-           saturation = number (snd.snd)
-       in  SigPS.constant saturation +
-           SigPS.exponential2 halfLife amplitude)
-      (SigP.runChunky $
-       let releaseTime = vectorTime fst * 5
-           releaseHL   = time fst
-           amplitude   = number snd
-       in  CausalP.take (round ^<< releaseTime) $*
-           SigPS.exponential2 releaseHL amplitude)
-
-brass ::
-   IO (Real -> Real ->
-       Real -> Real -> Real -> Real ->
-       PC.T Real ->
-       PC.T Real ->
-       SigSt.ChunkSize ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-brass =
-   liftA2
-      (\osc env attTime attPeak attHL dec rel emph det dist vcsize fm sr vel freq dur ->
-         osc
-            (sr,
-             ((det, dist), (fm,freq),
-              env attTime emph attHL dec rel vcsize sr vel dur))
-            (env attTime attPeak attHL dec rel vcsize sr vel dur))
-      (let det  = control (fst.fst3)
-           dist = control (snd.fst3)
-           fm   = modulation snd3
-           emph = signal thd3
-           osci ::
-              Param.T p Real ->
-              CausalP.T p
-                 (VectorValue,
-                       {- wave shrink/replication factor -}
-                  (VectorValue, VectorValue)
-                       {- detune, frequency modulation -})
-                 VectorValue
-           osci d =
-              CausalPS.shapeModOsci WaveL.rationalApproxSine1
-              <<<
-              second
-                 (CausalP.feedFst zero
-                  <<<
-                  CausalP.envelope
-                  <<<
-                  first (one + CausalPS.amplify d))
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $>
-              (phaserOsci osci
-               <<<
-               CausalP.feedFst (piecewiseConstantVector dist)
-               <<<
-               CausalP.feedSnd (frequencyFromBendModulation (frequencyConst 5) fm)
-               <<<
-               (CausalP.envelope $< piecewiseConstantVector det)
-               $*
-               SigP.fromStorableVectorLazy emph)))
-      adsr
-
-
-sampledSound ::
-   IO (Sample.T ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-sampledSound =
-   liftA2
-      (\osc freqMod smp fm sr vel freq dur ->
-         {-
-         We split the frequency modulation signal
-         in order to get a smooth frequency modulation curve.
-         Without (periodic) frequency modulation
-         we could just split the piecewise constant control curve @fm@.
-         -}
-         let fmSig =
-                freqMod
-                   (chunkSizesFromLazyTime (PC.duration fm))
-                   (sr, (fm, freq * Sample.period pos)) :: SigSt.T Vector
-             pos = Sample.positions smp
-             amp = 2 * amplitudeFromVelocity vel
-             (attack, sustain, release) = Sample.parts smp
-         in  (\cont -> osc cont
-                (sr,
-                 (amp,
-                  attack `SigSt.append`
-                  SVL.cycle (SigSt.take (Sample.loopLength pos) sustain),
-                  chunkSizesFromLazyTime dur))
-                fmSig)
-             (osc (const SigSt.empty)
-                (sr, (amp, release, NonNegChunky.fromChunks (repeat 1000)))))
-      (CausalP.runStorableChunkyCont
-         (let amp = number fst3
-              smp = signal snd3
-              dur = parameter thd3
-          in  CausalPS.amplifyStereo amp
-              <<<
-              CausalP.stereoFromMono
-                 (CausalPS.pack
-                    (CausalP.frequencyModulationLinear
-                       (SigP.fromStorableVectorLazy smp)))
-              <<<
-              liftA2 Stereo.cons
-                 (CausalPS.amplify 0.999)
-                 (CausalPS.amplify 1.001)
-              <<<
-              arr fst
-              <<<
-              CausalP.feedSnd (SigP.lazySize dur)))
-      (SigP.runChunkyPattern
-         (frequencyFromBendModulation (frequencyConst 3) (modulation id)))
-
-
-_sampledSoundLeaky ::
-   IO (Sample.T ->
-       PC.T (BM.T Real) ->
-       Instrument Real (Stereo.T Vector))
-_sampledSoundLeaky =
-   liftA2
-      (\osc freqMod smp fm sr vel freq dur ->
-         {-
-         We split the frequency modulation signal
-         in order to get a smooth frequency modulation curve.
-         Without (periodic) frequency modulation
-         we could just split the piecewise constant control curve @fm@.
-         -}
-         let (sustainFM, releaseFM) =
-                SVP.splitAt (chunkSizesFromLazyTime dur) $
-                (freqMod
-                   (chunkSizesFromLazyTime (PC.duration fm))
-                   (sr, (fm, freq * Sample.period pos)) :: SigSt.T Vector)
-             pos = Sample.positions smp
-             amp = 2 * amplitudeFromVelocity vel
-             (attack, sustain, release) = Sample.parts smp
-         in  osc
-                (sr,
-                 (amp,
-                  attack `SigSt.append`
-                  SVL.cycle (SigSt.take (Sample.loopLength pos) sustain)))
-                sustainFM
-             `SigSt.append`
-             osc (sr, (amp,release)) releaseFM)
-      (CausalP.runStorableChunky
-         (let smp = signal snd
-              amp = number fst
-          in  CausalPS.amplifyStereo amp
-              <<<
-              CausalP.stereoFromMono
-                 (CausalPS.pack
-                    (CausalP.frequencyModulationLinear
-                       (SigP.fromStorableVectorLazy smp)))
-              <<<
-              liftA2 Stereo.cons
-                 (CausalPS.amplify 0.999)
-                 (CausalPS.amplify 1.001)))
-      (SigP.runChunkyPattern
-         (frequencyFromBendModulation (frequencyConst 3) (modulation id)))
+   tonal noise can be produced by modulating pink noise
+      experimental: multiply with waveforms other than sine
+   use bits of an ASCII code as waveform
+   use a greymap picture as source of waveforms
+   mix of detuned noisy-waverforms, try different and uniform waveforms
+   mix of sawtooth, where every sawtooth is modulated with red noise
+   mix of sine with harmonics where every harmonic is modulated differently
+   Flute: sine + filtered noise
+   Drum with various parameters
+   derive percussive instruments from fmString and arcString (for bass synths)
+   an FM sound with a slowly changing timbre
+      by using a very slightly detuned frequency for the modulator
+   making a tone out of noise using time stretch with helix algorithm
+      a chorus effect could be applied by two successive helix stretches
+      or by mixture of two stretches signals
+      additionally a resonant filter could be applied
+   a kind of Karplus-Strong algorithm with a non-linear function of past values
+      e.g. y(t) = f(y(t-d), y(t-2*d))
+      where d is the tone period and f is non-linear, maybe chaotic function.
+      In order to limit the appearance of chaotic waveforms,
+      we could combine this with a lowpass filter.
+   let attack and release depend on On and Off velocity
+   tineStereoFM:
+      continuous control of the modulation index
+      by linear interpolation of waves between modulations with integral indices.
+      E.g. modulation index 2.3 means
+      0.7*modulation with index 2 and 0.3*modulation with index 3.
+
+effects:
+   reverb and controllable delay
+   phaser or Chebyshev filter
+   reverb where many single combs are mixed
+      every comb has ever-increasing frequency, but is faded in and out.
+      Should give an endless effect where the reverb becomes higher and higher.
+
+continuous sounds:
+   fly
+   water/bubbles
+      when I accidentally did not scale filter frequency with sample rate,
+      the filter sound much like water bubbles.
+      I think a control curve consisting of some ramps will do the same.
+   hail, Geiger counter, pitch applied by comb filter
+      at a very high impulse rate the impulses itself
+      can generate an almost periodic signal
+
+
+Speech sounds improvements (tomatensalat)
+   use PSOLA for transposition
+   To this end divide signal into tonal part and residue (noise)
+   by a comb filter.
+   Maybe a non-linear comb filter may help,
+   that selects the center value from the filter window,
+   if the side values are similar
+   and returns zero, if the the side values differ too much.
+   Process the tonal part by PSOLA and
+   simply mix it with the non-tonal part on replay.
+
+Harmonizer-like:
+   We like to input an audio signal of speech
+   and a set of keys, and the speech is extended to chords
+   according to the pressed keys.
+   The lowest key is interpreted as base frequency of the input audio speech.
+   A PSOLA method transposes the audio input.
+
+Resonant filter controlled by keys
+   applied to an audio input signal
+   or an ordinary audio signal generated by other keys.
+   The splitting of keys however could be performed
+   by a MIDI event stream editor.
+-}
+
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE EmptyDataDecls #-}
+module Synthesizer.LLVM.Server.Packed.Instrument (
+   InputArg(..),
+   FrequencyControl,
+   Modulation,
+   DetuneModulation,
+
+   pingRelease,
+   pingStereoRelease,
+   pingStereoReleaseFM,
+   squareStereoReleaseFM,
+   bellStereoFM,
+   bellNoiseStereoFM,
+   tine,
+   tineStereo,
+   softString,
+   softStringFM,
+   tineStereoFM,
+   tineControlledFM,
+   fenderFM,
+   tineModulatorBankFM,
+   tineBankFM,
+   resonantFMSynth,
+   softStringDetuneFM,
+   softStringShapeFM, cosineStringStereoFM,
+   arcSineStringStereoFM, arcTriangleStringStereoFM,
+   arcSquareStringStereoFM, arcSawStringStereoFM,
+   fmStringStereoFM,
+   wind,
+   windPhaser,
+   filterSawStereoFM,
+   brass,
+   sampledSound,
+
+   -- * helper functions
+   stereoNoise,
+   frequencyFromBendModulation,
+   piecewiseConstantVector,
+
+   -- * for testing
+   pingReleaseEnvelope,
+   adsr,
+   ) where
+
+import Synthesizer.LLVM.Server.CommonPacked
+import Synthesizer.LLVM.Server.Common
+
+import qualified Synthesizer.LLVM.Server.SampledSound as Sample
+import qualified Synthesizer.LLVM.MIDI.BendModulation as BM
+import qualified Synthesizer.LLVM.ConstantPiece as Const
+import qualified Synthesizer.MIDI.PiecewiseConstant as PC
+import qualified Synthesizer.MIDI.EventList as Ev
+
+import Synthesizer.MIDI.Storable (chunkSizesFromLazyTime)
+
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
+import qualified Synthesizer.LLVM.Filter.Universal as UniFilterL
+import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
+import qualified Synthesizer.LLVM.Filter.Moog as MoogL
+import qualified Synthesizer.LLVM.MIDI as MIDIL
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.ControlledPacked as CtrlPS
+import qualified Synthesizer.LLVM.Causal.ProcessPacked as CausalPS
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Causal.Functional as F
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Storable.Signal as SigStL
+import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame as Frame
+import qualified Synthesizer.LLVM.Wave as WaveL
+import Synthesizer.LLVM.Causal.Process (($<#), ($*), ($<), ($>))
+import Synthesizer.LLVM.Causal.Functional (($&), (&|&))
+
+import qualified LLVM.DSL.Expression as Expr
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.Core as LLVM
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Synthesizer.Causal.Class         as CausalClass
+import qualified Synthesizer.Generic.Cut          as CutG
+import qualified Synthesizer.Storable.Signal      as SigSt
+import qualified Data.StorableVector.Lazy.Pattern as SVP
+import qualified Data.StorableVector.Lazy         as SVL
+
+import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilter
+
+import qualified Control.Monad.HT as M
+import Control.Arrow ((<<<), (^<<), (<<^), (&&&), (***), arr, first, second)
+import Control.Category (id)
+import Control.Applicative (liftA2, liftA3)
+
+import qualified Data.Traversable as Trav
+import Data.Traversable (traverse)
+import Data.Semigroup ((<>))
+
+import Data.Tuple.HT (fst3, snd3, thd3)
+
+import qualified Numeric.NonNegative.Chunky as NonNegChunky
+
+import qualified Algebra.Additive as Additive
+
+import NumericPrelude.Numeric (zero, one, round, (^?), (+), (-), (*))
+import Prelude hiding (Real, round, break, id, (+), (-), (*))
+
+
+
+frequencyControl ::
+   (MultiValue.Field a, MultiValue.RationalConstant a) =>
+   SampleRate (Exp a) ->
+   Sig.T (Const.T (MultiValue.T a)) ->
+   Sig.T (Const.T (MultiValue.T a))
+frequencyControl sr xs = Const.causalMap (frequency sr) $* xs
+
+data FrequencyControl a
+
+instance
+   (a ~ Exp b, MultiValue.Field b, MultiValue.RationalConstant b) =>
+      Input (FrequencyControl b) a where
+   data InputArg (FrequencyControl b) a =
+         FrequencyControl (Sig.T (Const.T (MultiValue.T b)))
+   type InputSource (FrequencyControl b) a =
+         Sig.T (Const.T (MultiValue.T b))
+   evalInput sampleRate =
+      FrequencyControl . frequencyControl sampleRate
+
+
+modulation ::
+   (MultiValue.Field a, MultiValue.RationalConstant a) =>
+   SampleRate (Exp a) ->
+   (Sig.T (Const.T (MultiValue.T (BM.T a))), Exp a) ->
+   Sig.T (Const.T (BM.T (MultiValue.T a)))
+modulation sr (fm,freq) =
+   transposeModulation sr freq (fmap BM.unMultiValue <$> fm)
+
+data Modulation a
+
+instance
+   (a ~ Exp b, MultiValue.Field b, MultiValue.RationalConstant b) =>
+      Input (Modulation b) a where
+   data InputArg (Modulation b) a =
+         Modulation (Sig.T (Const.T (BM.T (MultiValue.T b))))
+   type InputSource (Modulation b) a =
+         (Sig.T (Const.T (MultiValue.T (BM.T b))), Exp b)
+   evalInput sampleRate (fm,freq) =
+      Modulation $ modulation sampleRate (fm,freq)
+
+
+detuneModulation ::
+   (MultiValue.Field a, MultiValue.RationalConstant a) =>
+   SampleRate (Exp a) ->
+   (b, Sig.T (Const.T (MultiValue.T (BM.T a))), Exp a) ->
+   (b, Sig.T (Const.T (BM.T (MultiValue.T a))))
+detuneModulation sr (det,fm,freq) =
+   (det, transposeModulation sr freq (fmap BM.unMultiValue <$> fm))
+
+data DetuneModulation a
+
+instance
+   (a ~ Exp b, MultiValue.Field b, MultiValue.RationalConstant b) =>
+      Input (DetuneModulation b) a where
+   data InputArg (DetuneModulation b) a =
+         DetuneModulation
+            (Sig.T (Const.T (MultiValue.T b)),
+             Sig.T (Const.T (BM.T (MultiValue.T b))))
+   type InputSource (DetuneModulation b) a =
+         (Sig.T (Const.T (MultiValue.T b)),
+          Sig.T (Const.T (MultiValue.T (BM.T b))),
+          Exp b)
+   evalInput sampleRate (det,fm,freq) =
+      DetuneModulation $ detuneModulation sampleRate (det,fm,freq)
+
+
+type RealValue = MultiValue.T Real
+
+frequencyFromBendModulation ::
+   Exp Real ->
+   Sig.T (Const.T (BM.T RealValue)) ->
+   Sig.T VectorValue
+frequencyFromBendModulation speed fmFreq =
+   MIDIL.frequencyFromBendModulationPacked speed $* piecewiseConstant fmFreq
+
+stereoFrequenciesFromDetuneBendModulation ::
+   Exp Real ->
+   (Sig.T (Const.T RealValue), Sig.T (Const.T (BM.T RealValue))) ->
+   Sig.T (Stereo.T VectorValue)
+stereoFrequenciesFromDetuneBendModulation speed (det,fm) =
+   (Causal.envelopeStereo $< frequencyFromBendModulation speed fm)
+   <<<
+   liftA2 Stereo.cons (one + id) (one - id)
+   $* piecewiseConstantVector det
+
+piecewiseConstantVector :: Sig.T (Const.T RealValue) -> Sig.T VectorValue
+piecewiseConstantVector xs =
+   piecewiseConstant (Const.causalMap Serial.upsample $* xs)
+
+pingReleaseEnvelope ::
+   IO (Real -> Real ->
+       SigSt.ChunkSize ->
+       SampleRate Real -> Real -> Ev.LazyTime -> SigSt.T Vector)
+pingReleaseEnvelope =
+   liftA2
+      (\pressed release decay rel vcsize sr vel dur ->
+         SigStL.continuePacked
+            (pioApplyToLazyTime (pressed sr decay vel) dur)
+            (\x -> release vcsize sr rel x))
+      (CausalRender.run $
+       wrapped $ \(Time decay) (Number velocity) (SampleRate _sr) ->
+       Causal.fromSignal
+         (SigPS.exponential2 decay (amplitudeFromVelocity velocity)))
+      (Render.run $
+       wrapped $ \(Time releaseHL) (Number amplitude) (SampleRate _sr) ->
+       let releaseTime = releaseHL * 5 / fromIntegral vectorSize
+       in Causal.take (Expr.roundToIntFast releaseTime) $*
+          SigPS.exponential2 releaseHL amplitude)
+
+pingRelease ::
+   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real Vector)
+pingRelease =
+   liftA2
+      (\osc env dec rel vcsize sr vel freq dur ->
+         pioApply (osc sr freq) (env dec rel vcsize sr vel dur))
+      (CausalRender.run $ wrapped $ \(Frequency freq) (SampleRate _sr) ->
+         Causal.envelope $> SigPS.osci WaveL.saw zero freq)
+      pingReleaseEnvelope
+
+pingStereoRelease ::
+   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Vector))
+pingStereoRelease =
+   liftA2
+      (\osc env dec rel vcsize sr vel freq dur ->
+         pioApply (osc sr freq) (env dec rel vcsize sr vel dur))
+      (CausalRender.run $ wrapped $ \(Frequency freq) (SampleRate _sr) ->
+         Stereo.multiValue <$>
+         Causal.envelopeStereo $>
+         liftA2 Stereo.cons
+            (SigPS.osci WaveL.saw zero (0.999*freq))
+            (SigPS.osci WaveL.saw zero (1.001*freq)))
+      pingReleaseEnvelope
+
+pingStereoReleaseFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       PC.T Real ->
+       Real -> Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+pingStereoReleaseFM =
+   liftA2
+      (\osc env dec rel detune shape phase phaseDecay vcsize fm
+            sr vel freq dur ->
+         pioApply
+            (osc sr (phase, phaseDecay) shape (detune, fm, freq))
+            (env dec rel vcsize sr vel dur))
+      (CausalRender.run $
+       wrapped $
+         \(Number phase, Time decay) (Control shape) (DetuneModulation fm) ->
+       constant frequency 10 $ \speed _sr ->
+         Stereo.multiValue <$>
+         Causal.envelopeStereo $>
+         ((Causal.stereoFromMonoControlled
+             (CausalPS.shapeModOsci WaveL.rationalApproxSine1)
+               $< piecewiseConstantVector shape)
+             <<^ Stereo.interleave
+           $< (liftA2 Stereo.cons id (Additive.negate id)
+                $* SigPS.exponential2 decay phase)
+           $* stereoFrequenciesFromDetuneBendModulation speed fm))
+      pingReleaseEnvelope
+
+{- |
+Square like wave constructed as difference
+of two phase shifted sawtooth like oscillations.
+-}
+squareStereoReleaseFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+squareStereoReleaseFM =
+   liftA2
+      (\osc env dec rel detune shape phase vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr (phase, shape) (detune, fm, freq))
+            (env dec rel vcsize sr vel dur))
+      (CausalRender.run $
+       wrapped $ \(Control phs, Control shp) (DetuneModulation fm) ->
+       constant frequency 10 $ \speed _sr ->
+         (let chanOsci ::
+                 Causal.T
+                    ((VectorValue, VectorValue), VectorValue)
+                    VectorValue
+              chanOsci =
+                 ((CausalPS.shapeModOsci WaveL.rationalApproxSine1
+                   <<<
+                   second (first (Additive.negate id)))
+                  -
+                   CausalPS.shapeModOsci WaveL.rationalApproxSine1)
+                 <<^
+                 (\((p,s),f) -> (s,(p,f)))
+          in Stereo.multiValue <$>
+             Causal.envelopeStereo $>
+              ((Causal.stereoFromMonoControlled chanOsci
+                   $< liftA2 (,)
+                         (piecewiseConstantVector phs)
+                         (piecewiseConstantVector shp))
+                $* stereoFrequenciesFromDetuneBendModulation speed fm)))
+      pingReleaseEnvelope
+
+
+type Triple a = (a, a, a)
+
+bellStereoFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+bellStereoFM =
+   liftA2
+      (\osc env dec rel detune vcsize fm sr vel freq dur ->
+         pioApply
+             (osc sr (detune, fm, freq) vel
+                  (env (dec/4) rel vcsize sr vel dur)
+                  (env (dec/7) rel vcsize sr vel dur))
+             (env dec rel vcsize sr vel dur))
+      (CausalRender.run $
+       wrapped $
+       \(DetuneModulation fm) (Number vel) (Signal env4) (Signal env7) ->
+       constant frequency 5 $ \speed _sr ->
+         (let osci ::
+                 (Triple VectorValue -> VectorValue) ->
+                 Exp Real ->
+                 Exp Real ->
+                 Causal.T
+                    (Triple VectorValue, Stereo.T VectorValue)
+                    (Stereo.T VectorValue)
+              osci sel v d =
+                 Causal.envelopeStereo
+                 <<<
+                 (arr sel ***
+                    (CausalPS.amplifyStereo v
+                     <<<
+                     Causal.stereoFromMono
+                        (CausalPS.osci WaveL.approxSine4 $< zero)
+                     <<<
+                     CausalPS.amplifyStereo d))
+          in  Stereo.multiValue <$>
+              sumNested
+                 [osci fst3  0.6              1,
+                  osci snd3 (0.02 *  50^?vel) 4,
+                  osci thd3 (0.02 * 100^?vel) 7]
+              <<<
+              CausalClass.feedSnd
+                 (stereoFrequenciesFromDetuneBendModulation speed fm)
+              <<<
+              arr (\(e1,(e4,e7)) -> (e1,e4,e7))
+               $> {-
+                  Be careful, those storable vectors shorten the whole sound
+                  if they have shorter release than the main envelope.
+                  -}
+                  liftA2 (,) env4 env7))
+      pingReleaseEnvelope
+
+bellNoiseStereoFM ::
+   IO (Real -> Real ->
+       PC.T Real -> PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+bellNoiseStereoFM =
+   liftA2
+      (\osc env dec rel noiseAmp noiseReson vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr (fm, freq) (noiseAmp, noiseReson) vel
+               (env (dec/4) rel vcsize sr vel dur)
+               (env (dec/7) rel vcsize sr vel dur))
+            (env dec rel vcsize sr vel dur))
+      (CausalRender.run $
+       wrapped $
+       \(Modulation fm) (Control noiseAmp, Control noiseReson)
+         (Number vel) (Signal env4) (Signal env7) ->
+       constant noiseReference 20000 $ \noiseRef ->
+       constant frequency 5 $ \speed _sr ->
+         (let osci ::
+                 (Triple VectorValue -> VectorValue) ->
+                 Exp Real ->
+                 Exp Real ->
+                 Causal.T (Triple VectorValue, VectorValue) VectorValue
+              osci sel v d =
+                 Causal.envelope
+                 <<<
+                 (arr sel ***
+                    (CausalPS.amplify v
+                     <<<
+                     (CausalPS.osci WaveL.approxSine4 $< zero)
+                     <<<
+                     CausalPS.amplify d))
+
+              noise ::
+                 (Triple VectorValue -> VectorValue) ->
+                 Exp Real ->
+                 Causal.T (Triple VectorValue, VectorValue) VectorValue
+              noise sel d =
+                 (Causal.envelope $< piecewiseConstantVector noiseAmp)
+                 <<<
+                 Causal.envelope
+                 <<<
+                 (arr sel ***
+                    ({- UniFilter.lowpass
+                        ^<< -}
+                     (CtrlPS.process $> SigPS.noise 12 noiseRef)
+                     <<<
+{-
+                     (Causal.quantizeLift
+                        (Causal.zipWith UniFilterL.parameter)
+                        $<# (128 / fromIntegral vectorSize :: Real))
+-}
+                     (Causal.quantizeLift
+                        (Causal.zipWith (MoogL.parameter TypeNum.d8))
+                        $<# (128 / fromIntegral vectorSize :: Real))
+                     <<<
+                     CausalClass.feedFst (piecewiseConstant noiseReson)
+                     <<<
+                     Causal.map Serial.subsample
+                     <<<
+                     CausalPS.amplify d))
+          in  liftA2 Stereo.consMultiValue
+                 (sumNested
+                    [osci fst3  0.6              (1*0.999),
+                     osci snd3 (0.02 *  50^?vel) (4*0.999),
+                     osci thd3 (0.02 * 100^?vel) (7*0.999),
+                     noise fst3 0.999])
+                 (sumNested
+                    [osci fst3  0.6              (1*1.001),
+                     osci snd3 (0.02 *  50^?vel) (4*1.001),
+                     osci thd3 (0.02 * 100^?vel) (7*1.001),
+                     noise fst3 1.001])
+              <<<
+              CausalClass.feedSnd (frequencyFromBendModulation speed fm)
+              <<<
+              arr (\(e1,(e4,e7)) -> (e1,e4,e7))
+               $> {-
+                  Be careful, those storable vectors shorten the whole sound
+                  if they have shorter release than the main envelope.
+                  -}
+                  liftA2 (,) env4 env7))
+      pingReleaseEnvelope
+
+
+tine :: IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real Vector)
+tine =
+   liftA2
+      (\osc env dec rel vcsize sr vel freq dur ->
+         pioApply (osc sr vel freq) (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $ \(Number vel) (Frequency freq) ->
+       constant time 1 $ \halfLife _sr ->
+         (Causal.envelope $>
+            (CausalPS.osci WaveL.approxSine2
+               $> SigPS.constant freq
+               $* (Causal.envelope
+                     $< SigPS.exponential2 halfLife (vel+1)
+                     $* SigPS.osci WaveL.approxSine2 zero (2*freq)))))
+      pingReleaseEnvelope
+
+tineStereo ::
+   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Vector))
+tineStereo =
+   liftA2
+      (\osc env dec rel vcsize sr vel freq dur ->
+         pioApply (osc sr vel freq) (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $ \(Number vel) (Frequency freq) ->
+       constant time 1 $ \halfLife _sr ->
+         (let chanOsci d =
+                 CausalPS.osci WaveL.approxSine2 $> SigPS.constant (freq*d)
+          in Stereo.multiValue <$>
+             Causal.envelopeStereo $>
+               (liftA2 Stereo.cons (chanOsci 0.995) (chanOsci 1.005)
+                  $* (SigPS.exponential2 halfLife (vel+1) *
+                      SigPS.osci WaveL.approxSine2 zero (2*freq)))))
+      pingReleaseEnvelope
+
+
+softStringReleaseEnvelope ::
+   IO (Real -> SampleRate Real -> Real -> Ev.LazyTime -> SigSt.T Vector)
+softStringReleaseEnvelope =
+   liftA2
+      (\rev env attackTime sr vel dur ->
+         let attackTimeVector :: Word
+             attackTimeVector = round (attackTime * vectorRate sr)
+             {-
+             release <- take attackTime beginning
+             would yield a space leak, thus we first split 'beginning'
+             and then concatenate it again
+             -}
+             {-
+             We can not easily generate attack and sustain separately,
+             because we want to use the chunk structure implied by 'dur'.
+             -}
+             (attack, sustain) =
+                SigSt.splitAt (fromIntegral attackTimeVector) $
+                pioApplyToLazyTime
+                  (env sr (amplitudeFromVelocity vel) attackTimeVector)
+                  dur
+             release = rev attack
+         in  attack <> sustain <> release)
+      SigStL.makeReversePacked
+      (CausalRender.run $
+       wrapped $ \(Number amp) (Parameter attackTimeVector) (SampleRate _sr) ->
+       Causal.fromSignal $
+           (<> SigPS.constant amp) $
+           (CausalPS.amplify amp <<<
+            Causal.take attackTimeVector
+            $* SigPS.parabolaFadeInInf
+                  (fromIntegral vectorSize *
+                   Expr.fromIntegral attackTimeVector)))
+
+softString :: IO (Instrument Real (Stereo.T Vector))
+softString =
+   liftA2
+      (\osc env sr vel freq dur ->
+         pioApply (osc sr freq) (env 1 sr vel dur))
+      (CausalRender.run $
+       wrapped $ \(Frequency freq) (SampleRate _sr) ->
+       let osci d = SigPS.osci WaveL.saw zero (d * freq)
+       in Stereo.multiValue <$>
+           Causal.envelopeStereo $>
+              (liftA2 Stereo.cons
+                 (osci 1.005 + osci 0.998)
+                 (osci 1.002 + osci 0.995)))
+      softStringReleaseEnvelope
+
+
+softStringFM :: IO (PC.T (BM.T Real) -> Instrument Real (Stereo.T Vector))
+softStringFM =
+   liftA2
+      (\osc env fm sr vel freq dur ->
+         pioApply (osc sr (fm, freq)) (env 1 sr vel dur))
+      (CausalRender.run $
+       wrapped $ \(Modulation fm) ->
+       constant frequency 5 $ \speed _sr ->
+       let osci d = (CausalPS.osci WaveL.saw $< zero) <<< CausalPS.amplify d
+       in Stereo.multiValue <$>
+           (Causal.envelopeStereo $>
+              (liftA2 Stereo.cons
+                  (osci 1.005 + osci 0.998)
+                  (osci 1.002 + osci 0.995)
+               $* frequencyFromBendModulation speed fm)))
+      softStringReleaseEnvelope
+
+
+tineStereoFM ::
+   IO (Real -> Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+tineStereoFM =
+   liftA2
+      (\osc env dec rel vcsize fm sr vel freq dur ->
+         pioApply (osc sr vel (fm, freq)) (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $ \(Number vel) (Modulation fm) ->
+       constant time 1 $ \halfLife ->
+       constant frequency 5 $ \speed _sr ->
+         (let chanOsci d =
+                 CausalPS.osci WaveL.approxSine2
+                    <<< second (CausalPS.amplify d)
+          in Stereo.multiValue <$>
+              Causal.envelopeStereo $>
+                 (liftA2 Stereo.cons (chanOsci 0.995) (chanOsci 1.005)
+                  <<<
+                  (((Causal.envelope
+                       $< SigPS.exponential2 halfLife (vel+1))
+                     <<< (CausalPS.osci WaveL.approxSine2 $< zero)
+                     <<< CausalPS.amplify 2)
+                   &&& id)
+                  $* frequencyFromBendModulation speed fm)))
+      pingReleaseEnvelope
+
+
+_tineControlledProc, tineControlledFnProc ::
+   Sig.T (Const.T RealValue) ->
+   Sig.T (Const.T RealValue) ->
+   Exp Real ->
+   SampleRate (Exp Real) ->
+   Causal.T (Stereo.T VectorValue) (Stereo.T VectorValue)
+_tineControlledProc index depth vel = constant time 1 $ \halfLife _sr ->
+   Causal.stereoFromMono (CausalPS.osci WaveL.approxSine2)
+   <<<
+   Stereo.interleave
+   ^<<
+   ((Causal.envelopeStereo
+       $< (piecewiseConstantVector depth
+           *
+           SigPS.exponential2 halfLife (vel+1)))
+    <<<
+    Causal.stereoFromMono (CausalPS.osci WaveL.approxSine2 $< zero)
+    <<<
+    (Causal.envelopeStereo $< piecewiseConstantVector index))
+            &&& id
+
+tineControlledFnProc index depth vel = constant time 1 $ \halfLife _sr ->
+   F.withGuidedArgs F.atom $ \freq ->
+      Causal.stereoFromMono (CausalPS.osci WaveL.approxSine2)
+      $&
+      liftA2 (liftA2 (,))
+         ((Causal.envelopeStereo
+             $< (piecewiseConstantVector depth
+                 *
+                 SigPS.exponential2 halfLife (vel+1)))
+          <<<
+          Causal.stereoFromMono (CausalPS.osci WaveL.approxSine2 $< zero)
+          <<<
+          (Causal.envelopeStereo $< piecewiseConstantVector index)
+          $&
+          freq)
+         freq
+
+tineControlledFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       PC.T Real -> PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+tineControlledFM =
+   liftA2
+      (\osc env dec rel detune index depth vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr (index, depth) vel (detune, fm, freq))
+            (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $ \(Control index, Control depth)
+          (Number vel) (DetuneModulation fm) ->
+       constant frequency 5 $ \speed sr ->
+         Stereo.multiValue <$>
+         Causal.envelopeStereo $>
+            (tineControlledFnProc index depth vel sr $*
+             stereoFrequenciesFromDetuneBendModulation speed fm))
+      pingReleaseEnvelope
+
+
+fenderProc ::
+   Sig.T (Const.T RealValue) ->
+   Sig.T (Const.T RealValue) ->
+   Sig.T (Const.T RealValue) ->
+   Exp Real ->
+   SampleRate (Exp Real) ->
+   Causal.T (Stereo.T VectorValue) (Stereo.T VectorValue)
+fenderProc fade index depth vel = constant time 1 $ \halfLife _sr ->
+   F.withGuidedArgs F.atom $ \stereoFreq ->
+       let channel_n_1 ::
+              F.T VectorValue VectorValue ->
+              F.T VectorValue VectorValue
+           channel_n_1 freq =
+              CausalPS.osci WaveL.approxSine2
+              $&
+              ((Causal.envelope
+                  $< (piecewiseConstantVector depth
+                      *
+                      SigPS.exponential2 halfLife (vel+1)))
+               <<<
+               (CausalPS.osci WaveL.approxSine2 $< zero)
+               <<<
+               (Causal.envelope $< piecewiseConstantVector index)
+               $&
+               freq)
+              &|&
+              freq
+           channel_1_2 ::
+              F.T VectorValue VectorValue ->
+              F.T VectorValue VectorValue
+           channel_1_2 freq =
+              CausalPS.osci WaveL.approxSine2
+              $&
+              ((Causal.envelope
+                  $< (piecewiseConstantVector depth
+                      *
+                      SigPS.exponential2 halfLife (vel+1)))
+               <<<
+               (CausalPS.osci WaveL.approxSine2 $< zero)
+               $&
+               freq)
+              &|&
+              (CausalPS.amplify 2 $& freq)
+       in  (Causal.stereoFromMonoControlled
+              (fadeProcess
+                 (F.compile $ channel_n_1 $ F.lift id)
+                 (F.compile $ channel_1_2 $ F.lift id))
+              $< piecewiseConstantVector fade)
+           $&
+           stereoFreq
+
+fenderFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       PC.T Real -> PC.T Real -> PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+fenderFM =
+   liftA2
+      (\osc env dec rel detune index depth fade vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr (index, depth) fade vel (detune, fm, freq))
+            (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $ \(Control index, Control depth) (Control fade)
+            (Number vel) (DetuneModulation fm) ->
+       constant frequency 5 $ \speed sr ->
+         Stereo.multiValue <$>
+         Causal.envelopeStereo $>
+            (fenderProc fade index depth vel sr $*
+             stereoFrequenciesFromDetuneBendModulation speed fm))
+      pingReleaseEnvelope
+
+
+fmModulator ::
+   Exp Real ->
+   Exp Real ->
+   Sig.T (Const.T RealValue) ->
+   SampleRate (Exp Real) ->
+   Causal.T (Stereo.T VectorValue) (Stereo.T VectorValue)
+fmModulator vel n depth = constant time 1 $ \halfLife _sr ->
+   (Causal.envelopeStereo
+      $< (piecewiseConstantVector depth
+          *
+          SigPS.exponential2 halfLife (vel+1)))
+   <<<
+   Causal.stereoFromMono (CausalPS.osci WaveL.approxSine2 $< zero)
+   <<<
+   CausalPS.amplifyStereo n
+
+tineModulatorBankFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       PC.T Real -> PC.T Real -> PC.T Real -> PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+tineModulatorBankFM =
+   liftA2
+      (\osc env
+            dec rel detune
+            depth1 depth2 depth3 depth4
+            vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr depth1 depth2 depth3 depth4 vel (detune, fm, freq))
+            (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $
+       \(Control depth1) (Control depth2) (Control depth3) (Control depth4)
+           (Number vel) (DetuneModulation fm) ->
+       constant frequency 5 $ \speed sr ->
+           Stereo.multiValue <$>
+              (Causal.envelopeStereo $>
+                 (Causal.stereoFromMono (CausalPS.osci WaveL.approxSine2)
+                  <<<
+                  Stereo.interleave
+                  ^<<
+                  sumNested
+                     [fmModulator vel 1 depth1 sr,
+                      fmModulator vel 2 depth2 sr,
+                      fmModulator vel 3 depth3 sr,
+                      fmModulator vel 4 depth4 sr]
+                    &&& id
+                  $*
+                  stereoFrequenciesFromDetuneBendModulation speed fm)))
+      pingReleaseEnvelope
+
+tineBankFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       PC.T Real -> PC.T Real -> PC.T Real -> PC.T Real ->
+       PC.T Real -> PC.T Real -> PC.T Real -> PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+tineBankFM =
+   liftA2
+      (\osc env
+            dec rel detune
+            depth1 depth2 depth3 depth4
+            partial1 partial2 partial3 partial4
+            vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr depth1 depth2 depth3 depth4
+               partial1 partial2 partial3 partial4
+               vel (detune, fm, freq))
+            (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $
+         \(Control depth1) (Control depth2) (Control depth3) (Control depth4)
+            (Control partial1) (Control  partial2)
+               (Control partial3) (Control partial4)
+            (Number vel) (DetuneModulation fm) ->
+       constant frequency 5 $ \speed sr ->
+
+         (let partial ::
+                 VectorValue -> Int -> VectorValue ->
+                 LLVM.CodeGenFunction r VectorValue
+              partial amp n t =
+                 A.mul amp =<<
+                 WaveL.partial WaveL.approxSine2 n t
+          in  Stereo.multiValue <$>
+              Causal.envelopeStereo $>
+                 (Causal.stereoFromMono
+                     (CausalPS.shapeModOsci
+                         (\(p1,(p2,(p3,p4))) t -> do
+                             y1 <- A.mul p1 =<< WaveL.approxSine2 t
+                             y2 <- partial p2 2 t
+                             y3 <- partial p3 3 t
+                             y4 <- partial p4 4 t
+                             A.add y1 =<< A.add y2 =<< A.add y3 y4)
+                        $<
+                           (liftA2 (,) (piecewiseConstantVector partial1) $
+                            liftA2 (,) (piecewiseConstantVector partial2) $
+                            liftA2 (,) (piecewiseConstantVector partial3)
+                                       (piecewiseConstantVector partial4)))
+                  <<<
+                  Stereo.interleave
+                  ^<<
+                  sumNested
+                     [fmModulator vel 1 depth1 sr,
+                      fmModulator vel 2 depth2 sr,
+                      fmModulator vel 3 depth3 sr,
+                      fmModulator vel 4 depth4 sr]
+                    &&& id
+                  $*
+                  stereoFrequenciesFromDetuneBendModulation speed fm)))
+      pingReleaseEnvelope
+
+
+{- |
+FM synthesis where the modulator is a resonantly filtered sawtooth.
+This way we get a sinus-like modulator where the sine frequency
+(that is, something like the modulation index) can be controlled continously.
+-}
+resonantFMSynthProc ::
+   Sig.T (Const.T RealValue) ->
+   Sig.T (Const.T RealValue) ->
+   Sig.T (Const.T RealValue) ->
+   Exp Real ->
+   SampleRate (Exp Real) ->
+   Causal.T (Stereo.T VectorValue) (Stereo.T VectorValue)
+resonantFMSynthProc reson index depth vel =
+   constant time 1 $ \halfLife _sr ->
+   F.withGuidedArgs (Stereo.cons F.atom F.atom) $ \stereoFreq ->
+       let chan :: F.T inp VectorValue -> F.T inp VectorValue
+           chan freq =
+              CausalPS.osci WaveL.approxSine2
+              $&
+              ((Causal.envelope
+                  $< (piecewiseConstantVector depth
+                      *
+                      SigPS.exponential2 halfLife (vel+1)))
+               <<<
+               UniFilter.lowpass
+               ^<<
+               CtrlPS.process
+               $&
+               (Causal.zipWith UniFilterL.parameter
+                   <<<
+                   CausalClass.feedFst (piecewiseConstant reson)
+                   <<<
+                   (Causal.envelope $< piecewiseConstant index)
+                   <<<
+                   Causal.map Serial.subsample
+                   $&
+                   freq)
+               &|&
+               ((CausalPS.osci WaveL.saw $< zero)
+                $&
+                freq))
+              &|&
+              freq
+       in  Trav.traverse chan stereoFreq
+
+resonantFMSynth ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       PC.T Real -> PC.T Real -> PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+resonantFMSynth =
+   liftA2
+      (\osc env dec rel detune reson index depth vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr (reson, index, depth) vel (detune, fm, freq))
+            (env dec rel vcsize sr 0 dur))
+      (CausalRender.run $
+       wrapped $
+       \(Control reson, Control index, Control depth)
+         (Number vel) (DetuneModulation fm) ->
+       constant frequency 5 $ \speed sr ->
+            Stereo.multiValue <$>
+            Causal.envelopeStereo $>
+               (resonantFMSynthProc reson index depth vel sr $*
+                stereoFrequenciesFromDetuneBendModulation speed fm))
+      pingReleaseEnvelope
+
+
+phaserOsci ::
+   (Exp Real -> Causal.T a VectorValue) ->
+   Causal.T a (Stereo.T VectorValue)
+phaserOsci osci =
+   CausalPS.amplifyStereo 0.25
+   <<<
+   liftA2 Stereo.cons
+      (sumNested $ map osci [1.0, -0.4, 0.5, -0.7])
+      (sumNested $ map osci [0.4, -1.0, 0.7, -0.5])
+
+
+softStringDetuneFM ::
+   IO (Real ->
+       PC.T Real ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+softStringDetuneFM =
+   liftA2
+      (\osc env att det fm sr vel freq dur ->
+         pioApply (osc sr det (fm, freq)) (env att sr vel dur))
+      (let osci :: Exp Real -> Causal.T (VectorValue, VectorValue) VectorValue
+           osci d =
+              (CausalPS.osci WaveL.saw $< zero)
+              <<<
+              Causal.envelope
+              <<<
+              first (one + CausalPS.amplify d)
+       in  CausalRender.run $
+           wrapped $ \(Control det) (Modulation fm) ->
+           constant frequency 5 $ \speed _sr ->
+           Stereo.multiValue <$>
+           (Causal.envelopeStereo $>
+              (phaserOsci osci
+               $< piecewiseConstantVector det
+               $* frequencyFromBendModulation speed fm)))
+      softStringReleaseEnvelope
+
+{-
+We might decouple the frequency of the enveloped tone
+from the frequency of the envelope,
+in order to get something like formants.
+-}
+softStringShapeFM, cosineStringStereoFM,
+  arcSineStringStereoFM, arcTriangleStringStereoFM,
+  arcSquareStringStereoFM, arcSawStringStereoFM ::
+   IO (Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+softStringShapeFM =
+   softStringShapeCore WaveL.rationalApproxSine1
+cosineStringStereoFM =
+   softStringShapeCore
+      (\k p -> WaveL.approxSine2 =<< WaveL.replicate k p)
+arcSawStringStereoFM = arcStringStereoFM WaveL.saw
+arcSineStringStereoFM = arcStringStereoFM WaveL.approxSine2
+arcSquareStringStereoFM = arcStringStereoFM WaveL.square
+arcTriangleStringStereoFM = arcStringStereoFM WaveL.triangle
+
+arcStringStereoFM ::
+   (forall r.
+    VectorValue ->
+    LLVM.CodeGenFunction r VectorValue) ->
+   IO (Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+arcStringStereoFM wave =
+   softStringShapeCore
+      (\k p ->
+         M.liftJoin2 Frame.amplifyMono
+            (WaveL.approxSine4 =<< WaveL.halfEnvelope p)
+            (wave =<< WaveL.replicate k p))
+
+softStringShapeCore ::
+   (forall r.
+    VectorValue ->
+    VectorValue ->
+    LLVM.CodeGenFunction r VectorValue) ->
+   IO (Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+softStringShapeCore wave =
+   liftA2
+      (\osc env att det dist fm sr vel freq dur ->
+         pioApply (osc sr det dist (fm, freq)) (env att sr vel dur))
+      (let osci ::
+              Exp Real ->
+              Causal.T
+                 (VectorValue,
+                       {- wave shape parameter -}
+                  (VectorValue, VectorValue)
+                       {- detune, frequency modulation -})
+                 VectorValue
+           osci d =
+              CausalPS.shapeModOsci wave
+              <<<
+              second
+                 (CausalClass.feedFst zero
+                  <<<
+                  Causal.envelope
+                  <<<
+                  first (one + CausalPS.amplify d))
+       in  CausalRender.run $
+           wrapped $ \(Control det) (Control dist) (Modulation fm) ->
+           constant frequency 5 $ \speed _sr ->
+           Stereo.multiValue <$>
+           (Causal.envelopeStereo $>
+              (phaserOsci osci
+               $< piecewiseConstantVector dist
+               $< piecewiseConstantVector det
+               $* frequencyFromBendModulation speed fm)))
+      softStringReleaseEnvelope
+
+fmStringStereoFM ::
+   IO (Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+fmStringStereoFM =
+   liftA2
+      (\osc env att det depth dist fm sr vel freq dur ->
+         pioApply (osc sr det depth dist (fm, freq)) (env att sr vel dur))
+      (let osci ::
+              Exp Real ->
+              Causal.T
+                 ((VectorValue, VectorValue)
+                       {- phase modulation depth, modulator distortion -},
+                  (VectorValue, VectorValue)
+                       {- detune, frequency modulation -})
+                 VectorValue
+           osci d =
+              CausalPS.osci WaveL.approxSine2
+              <<<
+              (Causal.envelope
+               <<<
+               second
+                  (CausalPS.shapeModOsci WaveL.rationalApproxSine1
+                     <<< second (CausalClass.feedFst zero))
+               <<^
+               (\((dp, ds), f) -> (dp, (ds, f))))
+               &&& arr snd
+              <<<
+              second (Causal.envelope <<< first (one + CausalPS.amplify d))
+       in  CausalRender.run $
+           wrapped $
+              \(Control det) (Control depth) (Control dist) (Modulation fm) ->
+           constant frequency 5 $ \speed _sr ->
+              Stereo.multiValue <$>
+              (Causal.envelopeStereo <<<
+                 (id &&&
+                  (phaserOsci osci
+                   <<<
+                   CausalClass.feedSnd
+                      (liftA2 (,)
+                         (piecewiseConstantVector det)
+                         (frequencyFromBendModulation speed fm))
+                   <<<
+                   CausalClass.feedSnd (piecewiseConstantVector dist)
+                   <<<
+                   (Causal.envelope $< piecewiseConstantVector depth)))))
+      softStringReleaseEnvelope
+
+
+stereoNoise :: SampleRate (Exp Real) -> Sig.T (Stereo.T VectorValue)
+stereoNoise =
+   constant noiseReference 20000 $ \noiseRef _sr ->
+   traverse
+      (\uid -> SigPS.noise uid noiseRef)
+      (Stereo.cons 13 14)
+
+windCore ::
+   Sig.T (Const.T RealValue) ->
+   Sig.T (Const.T (BM.T RealValue)) ->
+   SampleRate (Exp Real) ->
+   Sig.T (Stereo.T VectorValue)
+windCore reson fm =
+   constant frequency 0.2 $ \speed sr ->
+   Causal.stereoFromMonoControlled CtrlPS.process
+    $< (Causal.zipWith (MoogL.parameter TypeNum.d8)
+          $< piecewiseConstant reson
+          $* (Causal.map Serial.subsample $*
+                frequencyFromBendModulation speed fm))
+    $* stereoNoise sr
+
+wind ::
+   IO (Real ->
+       PC.T Real ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+wind =
+   liftA2
+      (\osc env att reson fm sr vel freq dur ->
+         pioApply (osc sr reson (fm, freq)) (env att sr vel dur))
+      (CausalRender.run $
+         wrapped $ \(Control reson) (Modulation fm) sr ->
+            Stereo.multiValue <$>
+            Causal.envelopeStereo $> windCore reson fm sr)
+      softStringReleaseEnvelope
+
+
+fadeProcess ::
+   (A.PseudoRing v, A.IntegerConstant v) =>
+   Causal.T a v ->
+   Causal.T a v ->
+   Causal.T (v, a) v
+fadeProcess proc0 proc1 =
+   let k = arr fst
+       a0 = proc0 <<^ snd
+       a1 = proc1 <<^ snd
+   in  (one-k)*a0 + k*a1
+
+
+windPhaser ::
+   IO (Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T Real ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+windPhaser =
+   liftA2
+      (\osc env att phaserMix phaserFreq reson fm sr vel freq dur ->
+         pioApply
+            (osc sr phaserMix phaserFreq reson (fm, freq))
+            (env att sr vel dur))
+      (CausalRender.run $
+         wrapped $
+           \(Control phaserMix) (FrequencyControl phaserFreq)
+              (Control reson) (Modulation fm) sr ->
+           Stereo.multiValue <$>
+           (Causal.envelopeStereo $>
+              ((Causal.stereoFromMonoControlled
+                   (fadeProcess (arr snd) CtrlPS.process
+                    <<<
+                    first (Causal.map Serial.upsample)
+                    <<^
+                    (\((k,p),x) -> (k,(p,x))))
+                  $< liftA2 (,)
+                        (piecewiseConstant phaserMix)
+                        (piecewiseConstant
+                           (Const.causalMap
+                              (Allpass.flangerParameter TypeNum.d8)
+                                 $* phaserFreq)))
+               $*
+               windCore reson fm sr)))
+      softStringReleaseEnvelope
+
+
+filterSawStereoFM ::
+   IO (Real -> Real ->
+       PC.T Real ->
+       Real -> Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+filterSawStereoFM =
+   liftA2
+      (\osc env dec rel detune bright brightDecay vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr bright brightDecay (detune, fm, freq))
+            (env dec rel vcsize sr vel dur))
+      (CausalRender.run $
+       wrapped $ \(Frequency bright) (Time brightDec) (DetuneModulation fm) ->
+       constant frequency 10 $ \speed ->
+       constant frequency 100 $ \cutoff _sr ->
+         (Stereo.multiValue <$>
+              Causal.envelopeStereo $>
+              (Causal.stereoFromMono
+                  (UniFilter.lowpass
+                   ^<<
+                   CtrlPS.processCtrlRate 100
+                      (\k ->
+                        Causal.map (UniFilterL.parameter 10) $*
+                           {- bound control in order to avoid too low resonant frequency,
+                              which makes the filter instable -}
+                           Sig.exponentialBounded2
+                              cutoff (brightDec/k) bright)
+                   <<<
+                   CausalPS.osci WaveL.saw $< zero)
+               $* stereoFrequenciesFromDetuneBendModulation speed fm)))
+      pingReleaseEnvelope
+
+
+{- |
+The ADSR curve is composed from three parts:
+Attack, Decay(+Sustain), Release.
+Attack starts when the key is pressed
+and lasts attackTime seconds
+where it reaches height attackPeak*amplitudeOfVelocity.
+It should be attackPeak>1 because in the following phase
+we want to approach 1 from above.
+Say the curve would approach the limit value L
+if it would continue after the end of the attack phase,
+the slope is determined by the halfLife with respect to this upper bound.
+That is, attackHalfLife is the time in seconds where the attack curve
+reaches or would reach L/2.
+After Attack the Decay part starts at the same level
+and decays to amplitudeOfVelocity.
+The slope is again a halfLife,
+that is, decayHalfLife is the time where the curve
+drops from attackPeak*amplitudeOfVelocity to (attackPeak+1)/2*amplitudeOfVelocity.
+This phase lasts as long as the key is pressed.
+If the key is released the curve decays with half life releaseHalfLife.
+-}
+{-
+1 - 2^(-attackTime/attackHalfLife) = peak
+-}
+adsr ::
+   IO (Real -> Real -> Real ->
+       Real -> Real ->
+       SigSt.ChunkSize ->
+       SampleRate Real -> Real -> Ev.LazyTime -> SigSt.T Vector)
+adsr =
+   liftA3
+      (\attack decay release
+           attackTime attackPeak attackHalfLife
+           decayHalfLife releaseHalfLife vcsize sr vel dur ->
+         let amp = amplitudeFromVelocity vel
+             (attackDur, decayDur) =
+                CutG.splitAt (round (attackTime * vectorRate sr)) dur
+         in SigStL.continuePacked
+               (pioApplyToLazyTime
+                  (attack sr
+                     attackHalfLife
+                     (attackPeak * amp / (1 - 2^?(-attackTime/attackHalfLife))))
+                  attackDur
+                <>
+                pioApplyToLazyTime
+                  (decay sr
+                     decayHalfLife
+                     ((attackPeak-1)*amp)
+                     amp)
+                  decayDur)
+               (\x -> release vcsize sr releaseHalfLife x))
+      (CausalRender.run $
+       wrapped $ \(Time halfLife) (Number amplitude) (SampleRate _sr) ->
+         Causal.fromSignal $
+         SigPS.constant amplitude - SigPS.exponential2 halfLife amplitude)
+      (CausalRender.run $ wrapped $
+         \(Time halfLife) (Number amplitude) (Number saturation)
+            (SampleRate _sr) ->
+         Causal.fromSignal $
+         SigPS.constant saturation + SigPS.exponential2 halfLife amplitude)
+      (Render.run $
+       wrapped $ \(Time releaseHL) (Number amplitude) (SampleRate _sr) ->
+       let releaseTime = releaseHL * 5 / fromIntegral vectorSize
+       in Causal.take (Expr.roundToIntFast releaseTime) $*
+          SigPS.exponential2 releaseHL amplitude)
+
+brass ::
+   IO (Real -> Real ->
+       Real -> Real -> Real -> Real ->
+       PC.T Real ->
+       PC.T Real ->
+       SigSt.ChunkSize ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+brass =
+   liftA2
+      (\osc env attTime attPeak attHL
+            dec rel emph det dist vcsize fm sr vel freq dur ->
+         pioApply
+            (osc sr det dist (fm, freq)
+               (env attTime emph attHL dec rel vcsize sr vel dur))
+            (env attTime attPeak attHL dec rel vcsize sr vel dur))
+      (let osci ::
+              Exp Real ->
+              Causal.T
+                 (VectorValue,
+                       {- wave shrink/replication factor -}
+                  (VectorValue, VectorValue)
+                       {- detune, frequency modulation -})
+                 VectorValue
+           osci d =
+              CausalPS.shapeModOsci WaveL.rationalApproxSine1
+              <<<
+              second
+                 (CausalClass.feedFst zero
+                  <<<
+                  Causal.envelope
+                  <<<
+                  first (one + CausalPS.amplify d))
+       in CausalRender.run $
+          wrapped $
+             \(Control det) (Control dist) (Modulation fm) (Signal emph) ->
+          constant frequency 5 $ \speed _sr ->
+            Stereo.multiValue <$>
+            Causal.envelopeStereo $>
+              (phaserOsci osci
+               <<<
+               CausalClass.feedFst (piecewiseConstantVector dist)
+               <<<
+               CausalClass.feedSnd (frequencyFromBendModulation speed fm)
+               <<<
+               (Causal.envelope $< piecewiseConstantVector det)
+               $*
+               emph))
+      adsr
+
+
+sampledSound ::
+   IO (Sample.T ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+sampledSound =
+   liftA2
+      (\osc freqMod smp fm sr vel freq dur ->
+         {-
+         We split the frequency modulation signal
+         in order to get a smooth frequency modulation curve.
+         Without (periodic) frequency modulation
+         we could just split the piecewise constant control curve @fm@.
+         -}
+         let fmSig :: SigSt.T Vector
+             fmSig =
+               pioApplyToLazyTime
+                  (freqMod sr (fm, freq * Sample.period pos))
+                  (PC.duration fm)
+             pos = Sample.positions smp
+             amp = 2 * amplitudeFromVelocity vel
+             (attack, sustain, release) = Sample.parts smp
+         in (\cont ->
+               pioApplyCont cont
+                  (osc sr amp
+                     (attack <>
+                      SVL.cycle (SigSt.take (Sample.loopLength pos) sustain))
+                     (chunkSizesFromLazyTime dur))
+                  fmSig)
+            (pioApplyCont (const SigSt.empty)
+               (osc sr amp release (NonNegChunky.fromChunks (repeat 1000)))))
+      (CausalRender.run $
+       wrapped $ \(Number amp) (Signal smp) (Signal dur) (SampleRate _sr) ->
+         Stereo.multiValue <$>
+         CausalPS.amplifyStereo amp
+              <<<
+              Causal.stereoFromMono
+                 (CausalPS.pack (Causal.frequencyModulationLinear smp))
+              <<<
+              liftA2 Stereo.cons
+                 (CausalPS.amplify 0.999)
+                 (CausalPS.amplify 1.001)
+              <<<
+              arr fst
+              <<<
+              CausalClass.feedSnd (Const.flatten dur))
+      (CausalRender.run $
+       wrapped $ \(Modulation fm) ->
+       constant frequency 3 $ \speed _sr ->
+         Causal.fromSignal $ frequencyFromBendModulation speed fm)
+
+
+_sampledSoundLeaky ::
+   IO (Sample.T ->
+       PC.T (BM.T Real) ->
+       Instrument Real (Stereo.T Vector))
+_sampledSoundLeaky =
+   liftA2
+      (\osc freqMod smp fm sr vel freq dur ->
+         {-
+         We split the frequency modulation signal
+         in order to get a smooth frequency modulation curve.
+         Without (periodic) frequency modulation
+         we could just split the piecewise constant control curve @fm@.
+         -}
+         let sustainFM, releaseFM :: SigSt.T Vector
+             (sustainFM, releaseFM) =
+               SVP.splitAt (chunkSizesFromLazyTime dur) $
+               pioApplyToLazyTime
+                  (freqMod sr (fm, freq * Sample.period pos))
+                  (PC.duration fm)
+             pos = Sample.positions smp
+             amp = 2 * amplitudeFromVelocity vel
+             (attack, sustain, release) = Sample.parts smp
+         in pioApply
+               (osc sr amp
+                  (attack <>
+                   SVL.cycle (SigSt.take (Sample.loopLength pos) sustain)))
+               sustainFM
+            <>
+            pioApply (osc sr amp release) releaseFM)
+      (CausalRender.run $
+       wrapped $ \(Number amp) (Signal smp) (SampleRate _sr) ->
+         Stereo.multiValue <$>
+              CausalPS.amplifyStereo amp
+              <<<
+              Causal.stereoFromMono
+                 (CausalPS.pack (Causal.frequencyModulationLinear smp))
+              <<<
+              liftA2 Stereo.cons
+                 (CausalPS.amplify 0.999)
+                 (CausalPS.amplify 1.001))
+      (CausalRender.run $
+       wrapped $ \(Modulation fm) ->
+       constant frequency 3 $ \speed _sr ->
+         Causal.fromSignal $ frequencyFromBendModulation speed fm)
diff --git a/src/Synthesizer/LLVM/Server/Parameter.hs b/src/Synthesizer/LLVM/Server/Parameter.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Server/Parameter.hs
+++ /dev/null
@@ -1,106 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-module Synthesizer.LLVM.Server.Parameter (
-   Tuple(..),
-   Frequency(..), Time(..), VectorTime(..), Number(..), Control(..), Signal(..),
-   withTuple2,
-   ) where
-
-import Synthesizer.LLVM.Server.CommonPacked (vectorSize)
-import Synthesizer.LLVM.Server.Common (Param, Real, SampleRate(SampleRate))
-
-import qualified Synthesizer.PiecewiseConstant.Signal as PC
-import qualified Synthesizer.Storable.Signal as SigSt
-
-import qualified LLVM.DSL.Parameter as Param
-
-import qualified Control.Category as Cat
-import Control.Applicative ((<$>))
-
-import qualified Data.Tuple.HT as TupleHT
-
-import Prelude hiding (Real)
-
-
-class Tuple tuple where
-   type Composed tuple :: *
-   type Source tuple :: *
-   decompose ::
-      Param (Source tuple) (SampleRate Real) ->
-      Param (Source tuple) (Composed tuple) -> tuple
-
-
-newtype Number p = Number (Param p Real)
-
-instance Tuple (Number p) where
-   type Composed (Number p) = Real
-   type Source (Number p) = p
-   decompose _sr t = Number t
-
-
-deconsSampleRate :: Param p (SampleRate a) -> Param p a
-deconsSampleRate = fmap (\(SampleRate sr) -> sr)
-
-newtype Time p = Time (Param p Real)
-
-instance Tuple (Time p) where
-   type Composed (Time p) = Real
-   type Source (Time p) = p
-   decompose sr t = Time (t * deconsSampleRate sr)
-
-newtype VectorTime p = VectorTime (Param p Real)
-
-instance Tuple (VectorTime p) where
-   type Composed (VectorTime p) = Real
-   type Source (VectorTime p) = p
-   decompose sr t =
-      VectorTime (t * deconsSampleRate sr / fromIntegral vectorSize)
-
-newtype Frequency p = Frequency (Param p Real)
-
-instance Tuple (Frequency p) where
-   type Composed (Frequency p) = Real
-   type Source (Frequency p) = p
-   decompose sr freq = Frequency (freq / deconsSampleRate sr)
-
-
-newtype Control p = Control (Param p (PC.T Real))
-
-instance Tuple (Control p) where
-   type Composed (Control p) = PC.T Real
-   type Source (Control p) = p
-   decompose _sr x = Control x
-
-
-newtype Signal p a = Signal (Param p (SigSt.T a))
-
-instance Tuple (Signal p a) where
-   type Composed (Signal p a) = SigSt.T a
-   type Source (Signal p a) = p
-   decompose _sr x = Signal x
-
-
-instance (Tuple a, Tuple b, Source a ~ Source b) => Tuple (a,b) where
-   type Composed (a,b) = (Composed a, Composed b)
-   type Source (a,b) = Source a
-   decompose sr p = (decompose sr $ fst <$> p, decompose sr $ snd <$> p)
-
-instance
-   (Tuple a, Tuple b, Tuple c, Source a ~ Source b, Source b ~ Source c) =>
-      Tuple (a,b,c) where
-   type Composed (a,b,c) = (Composed a, Composed b, Composed c)
-   type Source (a,b,c) = Source a
-   decompose sr p =
-      (decompose sr $ TupleHT.fst3 <$> p,
-       decompose sr $ TupleHT.snd3 <$> p,
-       decompose sr $ TupleHT.thd3 <$> p)
-
-
-withTuple2 ::
-   (Tuple tuple, Source tuple ~ p, Composed tuple ~ p) =>
-   (tuple -> f (SampleRate Real, p) a b) -> f (SampleRate Real, p) a b
-withTuple2 f =
-   idFromFunctor2 $ \param -> f $ decompose (fst<$>param) (snd<$>param)
-
--- cf. Param.idFromFunctor2
-idFromFunctor2 :: (Param.T p p -> f p a b) -> f p a b
-idFromFunctor2 f = f Cat.id
diff --git a/src/Synthesizer/LLVM/Server/Scalar/Instrument.hs b/src/Synthesizer/LLVM/Server/Scalar/Instrument.hs
--- a/src/Synthesizer/LLVM/Server/Scalar/Instrument.hs
+++ b/src/Synthesizer/LLVM/Server/Scalar/Instrument.hs
@@ -14,13 +14,17 @@
 
 import Synthesizer.LLVM.Server.Common
 import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Synthesizer.LLVM.Wave as WaveL
-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($>), ($*))
+import Synthesizer.Causal.Class (($<), ($>), ($*))
 
-import qualified LLVM.Core as LLVM
+import qualified LLVM.DSL.Expression as Expr
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import LLVM.DSL.Expression (Exp)
 
 import qualified Synthesizer.MIDI.EventList as Ev
 import Synthesizer.MIDI.Storable (chunkSizesFromLazyTime)
@@ -28,33 +32,29 @@
 import qualified Synthesizer.Storable.Signal      as SigSt
 import qualified Data.StorableVector.Lazy.Pattern as SigStV
 
-import Control.Arrow ((^<<), arr)
 import Control.Applicative (liftA, liftA2)
+import Data.Semigroup ((<>))
 
 import NumericPrelude.Numeric (zero, round, (+))
 import Prelude hiding (Real, round, break, (+))
 
 
-pingSig :: SigP.T (SampleRate Real, (Real, Real)) (LLVM.Value Real)
+pingSig ::
+   SampleRate (Exp Real) -> Exp Real -> Exp Real -> Sig.T (MultiValue.T Real)
 pingSig =
-   let vel = number fst
-       freq = frequency snd
-   in  CausalP.envelope
-          $< SigP.exponential2 (timeConst 0.2)
-                (fmap amplitudeFromVelocity vel)
-          $* SigP.osciSimple WaveL.saw zero freq
+   wrapped $ \(Number vel) (Frequency freq) ->
+   constant time 0.2 $ \halfLife _sr ->
+      Causal.envelope
+         $< Sig.exponential2 halfLife (amplitudeFromVelocity vel)
+         $* Sig.osci WaveL.saw zero freq
 
 ping :: IO (SigSt.ChunkSize -> SampleRate Real -> Real -> Real -> SigSt.T Real)
-ping =
-   fmap (\f chunkSize sr vel freq -> f chunkSize (sr, (vel,freq))) $
-   SigP.runChunky pingSig
+ping = Render.run pingSig
 
 pingDur :: IO (Instrument Real Real)
 pingDur =
-   fmap
-      (\sound sr vel freq dur ->
-         sound (chunkSizesFromLazyTime dur) (sr, (vel, freq))) $
-   SigP.runChunkyPattern pingSig
+   fmap (\sound sr vel freq -> pioApplyToLazyTime $ sound sr vel freq) $
+   CausalRender.run (\sr vel freq -> Causal.fromSignal $ pingSig sr vel freq)
 
 pingDurTake :: IO (SigSt.ChunkSize -> Instrument Real Real)
 pingDurTake =
@@ -77,41 +77,38 @@
    liftA2
       (\pressed release decay rel chunkSize sr vel dur ->
          SigStL.continue
-            (pressed (chunkSizesFromLazyTime dur) (sr, (decay,vel)))
-            (\x -> release chunkSize (sr, (rel,x))))
-      (SigP.runChunkyPattern $
-       let decay = time fst
-           velocity = number snd
-       in  SigP.exponential2 decay
-              (amplitudeFromVelocity ^<< velocity))
-      (SigP.runChunky $
-       let release = time fst
-           amplitude = number snd
-       in  (CausalP.take (round ^<< (release*3)) $*
-            SigP.exponential2 release amplitude))
+            (pioApplyToLazyTime (pressed sr decay vel) dur)
+            (\x -> release chunkSize sr rel x))
+      (CausalRender.run $
+       wrapped $ \(Time halfLife) (Number velocity) (SampleRate _sr) ->
+       Causal.fromSignal
+         (Sig.exponential2 halfLife (amplitudeFromVelocity velocity)))
+      (Render.run $
+       wrapped $ \(Time release) (Number amplitude) (SampleRate _sr) ->
+         Causal.take (Expr.roundToIntFast (release*3)) $*
+         Sig.exponential2 release amplitude)
 
 pingRelease :: IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real Real)
 pingRelease =
    liftA2
       (\osc env dec rel chunkSize sr vel freq dur ->
-         osc (sr, freq) (env dec rel chunkSize sr vel dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency id
-          in  CausalP.envelope $>
-              SigP.osciSimple WaveL.saw zero freq))
+         pioApply (osc sr freq) (env dec rel chunkSize sr vel dur))
+      (CausalRender.run $ frequency $+ \freq _sr ->
+         Causal.envelope $> Sig.osci WaveL.saw zero freq)
       pingReleaseEnvelope
 
-pingStereoRelease :: IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Real))
+pingStereoRelease ::
+   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Real))
 pingStereoRelease =
    liftA2
       (\osc env dec rel chunkSize sr vel freq dur ->
-         osc (sr, freq) (env dec rel chunkSize sr vel dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency id
-          in  CausalP.envelopeStereo $>
-              liftA2 Stereo.cons
-                 (SigP.osciSimple WaveL.saw zero (0.999*freq))
-                 (SigP.osciSimple WaveL.saw zero (1.001*freq))))
+         pioApply (osc sr freq) (env dec rel chunkSize sr vel dur))
+      (CausalRender.run $ frequency $+ \freq _sr ->
+         Stereo.multiValue <$>
+         Causal.envelopeStereo $>
+            liftA2 Stereo.cons
+               (Sig.osci WaveL.saw zero (0.999*freq))
+               (Sig.osci WaveL.saw zero (1.001*freq)))
       pingReleaseEnvelope
 
 
@@ -120,35 +117,35 @@
 tine =
    liftA2
       (\osc env dec rel chunkSize sr vel freq dur ->
-         osc (sr, (vel,freq)) (env dec rel chunkSize sr 0 dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency snd
-              vel  = number fst
-          in  CausalP.envelope $>
-                 (CausalP.osciSimple WaveL.approxSine2
-                    $> (SigP.constant freq)
-                    $* (CausalP.envelope
-                          $< SigP.exponential2 (timeConst 1) (vel+1)
-                          $* SigP.osciSimple WaveL.approxSine2 zero (2*freq)))))
+         pioApply (osc sr vel freq) (env dec rel chunkSize sr 0 dur))
+      (CausalRender.run $
+       wrapped $ \(Number vel) (Frequency freq) ->
+       constant time 1 $ \halfLife _sr ->
+         Causal.envelope $>
+         (Causal.osci WaveL.approxSine2
+            $> Sig.constant freq
+            $* (Causal.envelope
+                  $< Sig.exponential2 halfLife (vel+1)
+                  $* Sig.osci WaveL.approxSine2 zero (2*freq))))
       pingReleaseEnvelope
 
-tineStereo :: IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Real))
+tineStereo ::
+   IO (Real -> Real -> SigSt.ChunkSize -> Instrument Real (Stereo.T Real))
 tineStereo =
    liftA2
       (\osc env dec rel chunkSize sr vel freq dur ->
-         osc (sr, (vel,freq)) (env dec rel chunkSize sr 0 dur))
-      (CausalP.runStorableChunky
-         (let freq = frequency snd
-              vel  = number fst
-              chanOsci d =
-                 CausalP.osciSimple WaveL.approxSine2
-                    $> SigP.constant (freq*d)
-          in  CausalP.envelopeStereo $>
-                 (liftA2 Stereo.cons
-                     (chanOsci 0.995) (chanOsci 1.005)
-                  $* SigP.envelope
-                        (SigP.exponential2 (timeConst 1) (vel+1))
-                        (SigP.osciSimple WaveL.approxSine2 zero (2*freq)))))
+         pioApply (osc sr vel freq) (env dec rel chunkSize sr 0 dur))
+      (CausalRender.run $
+       wrapped $ \(Number vel) (Frequency freq) ->
+       constant time 1 $ \halfLife _sr ->
+         let chanOsci d =
+               Causal.osci WaveL.approxSine2 $> Sig.constant (freq*d)
+         in Stereo.multiValue <$>
+            Causal.envelopeStereo $>
+               (liftA2 Stereo.cons (chanOsci 0.995) (chanOsci 1.005) $*
+                  (Causal.envelope
+                     $< Sig.exponential2 halfLife (vel+1)
+                     $* Sig.osci WaveL.approxSine2 zero (2*freq))))
       pingReleaseEnvelope
 
 
@@ -158,8 +155,7 @@
 softStringReleaseEnvelope =
    liftA
       (\env attackTime (SampleRate sampleRate) vel dur ->
-         let attackTimeInt =
-                round (attackTime * sampleRate)
+         let attackTimeInt = round (attackTime * sampleRate)
              {-
              release <- take attackTime beginning
              would yield a space leak, thus we first split 'beginning'
@@ -171,29 +167,25 @@
              -}
              (attack, sustain) =
                 SigSt.splitAt attackTimeInt $
-                env (chunkSizesFromLazyTime dur)
-                    (fromIntegral attackTimeInt :: Real,
-                     amplitudeFromVelocity vel)
+                pioApplyToLazyTime
+                   (env
+                      (fromIntegral attackTimeInt :: Word)
+                      (amplitudeFromVelocity vel))
+                   dur
              release = SigSt.reverse attack
-         in  attack `SigSt.append` sustain `SigSt.append` release)
-      (let amp = arr snd
-           attackTime = arr fst
-       in  SigP.runChunkyPattern $
-           flip SigP.append (SigP.constant amp) $
-           SigP.amplify amp $
-           (SigP.parabolaFadeIn attackTime))
+         in attack <> sustain <> release)
+      (CausalRender.run $ \attackTime amp -> Causal.fromSignal $
+       Sig.amplify amp (Sig.parabolaFadeIn attackTime) <> Sig.constant amp)
 
 softString :: IO (Instrument Real (Stereo.T Real))
 softString =
    liftA2
-      (\osc env sr vel freq dur ->
-         osc (sr, freq) (env 1 sr vel dur))
-      (let freq = frequency id
-           osci d =
-              SigP.osciSimple WaveL.saw zero (d * freq)
-       in  CausalP.runStorableChunky $
-           (CausalP.envelopeStereo $>
-              (liftA2 Stereo.cons
-                 (osci 1.005 + osci 0.998)
-                 (osci 1.002 + osci 0.995))))
+      (\osc env sr vel freq dur -> pioApply (osc sr freq) (env 1 sr vel dur))
+      (CausalRender.run $ frequency $+ \freq _sr ->
+       let osci d = Sig.osci WaveL.saw zero (d * freq)
+       in Stereo.multiValue <$>
+          Causal.envelopeStereo $>
+            liftA2 Stereo.cons
+               (osci 1.005 + osci 0.998)
+               (osci 1.002 + osci 0.995))
       softStringReleaseEnvelope
diff --git a/src/Synthesizer/LLVM/Simple/Signal.hs b/src/Synthesizer/LLVM/Simple/Signal.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Simple/Signal.hs
+++ /dev/null
@@ -1,384 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-module Synthesizer.LLVM.Simple.Signal (
-   C(simple),
-   T,
-   amplify,
-   amplifyStereo,
-   constant,
-   envelope,
-   envelopeStereo,
-   exponential2,
-   iterate,
-   map,
-   mapAccum,
-   mix,
-   mixExt,
-   takeWhile,
-   empty,
-   append,
-   osci,
-   osciPlain,
-   osciSaw,
-   zip,
-   zipWith,
-
-   fromStorableVector,
-   fromStorableVectorLazy,
-
-   render,
-   renderChunky,
-   runChunky,
-   ) where
-
-import Synthesizer.LLVM.Simple.SignalPrivate hiding (alloca)
-
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-import qualified Synthesizer.LLVM.Frame as Frame
-import qualified Synthesizer.LLVM.Wave as Wave
-import qualified Synthesizer.LLVM.ForeignPtr as ForeignPtr
-
-import qualified Synthesizer.LLVM.Storable.ChunkIterator as ChunkIt
-import qualified Synthesizer.LLVM.Storable.Vector as SVU
-import qualified Data.StorableVector.Lazy as SVL
-import qualified Data.StorableVector as SV
-import qualified Data.StorableVector.Base as SVB
-
-import qualified LLVM.DSL.Execution as Exec
-
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-          (CodeGenFunction, ret, Value, valueOf,
-           IsFirstClass, IsSized, IsConst, IsArithmetic)
-
-import Control.Monad (liftM2)
-import Control.Applicative (pure, liftA2, liftA3, (<$>))
-
-import Data.Monoid (Monoid, mappend)
-
-import qualified Algebra.Transcendental as Trans
-
-import qualified System.Unsafe as Unsafe
-import Foreign.ForeignPtr (touchForeignPtr)
-import Foreign.Ptr (Ptr)
-import Data.Word (Word)
-import Control.Exception (bracket)
-
-import NumericPrelude.Numeric
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith, takeWhile)
-
-
-constant :: (C signal, IsConst a) => a -> signal (Value a)
-constant x = pure (valueOf x)
-
-mapAccum ::
-   (C signal, Memory.C s) =>
-   (forall r. a -> s -> CodeGenFunction r (b,s)) ->
-   (forall r. CodeGenFunction r s) ->
-   signal a -> signal b
-mapAccum f startS = alter (\(Core next start stop) ->
-   Core
-      (\ioContext (sa0,ss0) -> do
-         (a,sa1) <- next ioContext sa0
-         (b,ss1) <- MaybeCont.lift $ f a ss0
-         return (b, (sa1,ss1)))
-      (\ioContext ->
-         liftM2 (,) (start ioContext) startS)
-      (stop . fst))
-
-
-{- |
-Warning:
-This shortens the result to the shorter input signal.
-This is consistent with @Causal.mix@ but it may not be what you expect.
-Consider using 'mixExt' instead.
--}
-mix ::
-   (C signal, A.Additive a) =>
-   signal a -> signal a -> signal a
-mix = zipWith Frame.mix
-
-{- |
-The result of mixing is as long as the longer of the two input signals.
--}
-mixExt ::
-   (C signal, Monoid (signal (Value Bool, a)),
-    A.Additive a, Tuple.Phi a, Tuple.Undefined a) =>
-   signal a -> signal a -> signal a
-mixExt xs ys =
-   let ext zs =
-         mappend
-            ((,) (valueOf True) <$> zs)
-            (pure (valueOf False, A.zero))
-   in  fmap snd $ takeWhile (return . fst) $
-       zipWith
-         (\(cx,x) (cy,y) -> liftA2 (,) (A.or cx cy) (A.add x y))
-         (ext xs) (ext ys)
-
-
-{-
-You can apply Causal.takeWhile instead,
-but this requires a pretty complex type signature
-including a 'process' variable that is not of interest for the user.
--}
-takeWhile ::
-   (C signal) =>
-   (forall r. a -> CodeGenFunction r (Value Bool)) ->
-   signal a -> signal a
-takeWhile p =
-   alter
-      (\(Core next start stop) ->
-         Core
-            (\context sa0 -> do
-               (a,sa1) <- next context sa0
-               MaybeCont.guard =<< MaybeCont.lift (p a)
-               return (a,sa1))
-            start
-            stop)
-
-
-envelope ::
-   (C signal, A.PseudoRing a) =>
-   signal a -> signal a -> signal a
-envelope = zipWith Frame.amplifyMono
-
-envelopeStereo ::
-   (C signal, A.PseudoRing a) =>
-   signal a -> signal (Stereo.T a) -> signal (Stereo.T a)
-envelopeStereo = zipWith Frame.amplifyStereo
-
-amplify ::
-   (C signal, IsArithmetic a, IsConst a) =>
-   a -> signal (Value a) -> signal (Value a)
-amplify x =
-   map (Frame.amplifyMono (valueOf x))
-
-amplifyStereo ::
-   (C signal, IsArithmetic a, IsConst a) =>
-   a -> signal (Stereo.T (Value a)) -> signal (Stereo.T (Value a))
-amplifyStereo x =
-   map (Frame.amplifyStereo (valueOf x))
-
-
-
-iterate ::
-   (C signal, IsFirstClass a, IsSized a, IsConst a) =>
-   (forall r. Value a -> CodeGenFunction r (Value a)) ->
-   Value a -> signal (Value a)
-iterate f initial =
-   simple
-      (\y -> MaybeCont.lift $ fmap (\y1 -> (y,y1)) (f y))
-      (return initial)
-
-exponential2 ::
-   (C signal, Trans.C a, IsArithmetic a, IsSized a, IsConst a) =>
-   a -> a -> signal (Value a)
-exponential2 halfLife =
-   iterate (\y -> A.mul y (valueOf (0.5 ** recip halfLife))) . valueOf
-
-
-osciPlain ::
-   (C signal, SoV.Fraction t, IsSized t, IsConst t) =>
-   (forall r. Value t -> CodeGenFunction r y) ->
-   Value t -> Value t -> signal y
-osciPlain wave phase freq =
-   map wave $
-   iterate (SoV.incPhase freq) $
-   phase
-
-osci ::
-   (C signal, SoV.Fraction t, IsSized t, IsConst t) =>
-   (forall r. Value t -> CodeGenFunction r y) ->
-   t -> t -> signal y
-osci wave phase freq =
-   osciPlain wave (valueOf phase) (valueOf freq)
-
-osciSaw ::
-   (C signal, SoV.IntegerConstant a, SoV.Fraction a, IsSized a, IsConst a) =>
-   a -> a -> signal (Value a)
-osciSaw = osci Wave.saw
-
-
-
-fromStorableVector ::
-   (Storable.C a, Tuple.ValueOf a ~ value) => SV.Vector a -> T value
-fromStorableVector xs =
-   let (fp,ptr,l) = SVU.unsafeToPointers xs
-   in  Cons
-          (\_ () (p0,l0) -> do
-             cont <- MaybeCont.lift $ A.cmp LLVM.CmpGT l0 A.zero
-             MaybeCont.withBool cont $ do
-                y1 <- Storable.load p0
-                p1 <- Storable.incrementPtr p0
-                l1 <- A.dec l0
-                return (y1,(p1,l1)))
-          (return ())
-          (const $ return
-             (valueOf ptr,
-              valueOf (fromIntegral l :: Word)))
-          -- keep the foreign ptr alive
-          (return (fp, ()))
-          touchForeignPtr
-
-{-
-This function calls back into the Haskell function 'nextChunk'
-that returns a pointer to the data of the next chunk
-and advances to the next chunk in the sequence.
--}
-fromStorableVectorLazy ::
-   (Storable.C a, Tuple.ValueOf a ~ value) => SVL.Vector a -> T value
-fromStorableVectorLazy = flattenChunks . storableVectorChunks
-
-storableVectorChunks ::
-   (Storable.C a) => SVL.Vector a -> T (Value (Ptr a), Value Word)
-storableVectorChunks sig =
-   Cons
-      (storableVectorNextChunk "Simple.Signal.fromStorableVectorLazy.nextChunk")
-      LLVM.alloca
-      (const $ return ())
-      ((\stable -> (stable,stable)) <$> ChunkIt.new sig)
-      ChunkIt.dispose
-
-
-foreign import ccall safe "dynamic" derefFillPtr ::
-   Exec.Importer (Word -> Ptr struct -> IO Word)
-
-
-compile ::
-   (Storable.C a, Tuple.ValueOf a ~ value, Memory.C state) =>
-   (forall r z.
-    (Tuple.Phi z) => local -> state -> MaybeCont.T r z (value, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r. CodeGenFunction r state) ->
-   IO (Word -> Ptr a -> IO Word)
-compile next alloca start =
-   Exec.compile "signal" $
-      Exec.createFunction derefFillPtr "fillsignalblock" $ \ size bPtr -> do
-         s <- start
-         local <- alloca
-         (pos,_) <-
-               Storable.arrayLoopMaybeCont size bPtr s $ \ ptri s0 -> do
-            (y,s1) <- next local s0
-            MaybeCont.lift $ Storable.store y ptri
-            return s1
-         ret pos
-
-{-
-This parameter order would allows us to compile the code once
-and apply it to different signal lengths.
-However, we do not make use of this and instead bake
-parts of the IO context into the code to allow constant folding.
-The parameter order is consistent with that of @Parameterized.Signal.render@.
--}
-render ::
-   (Storable.C a, Tuple.ValueOf a ~ value, Memory.C value) =>
-   T value -> Int -> SV.Vector a
-render (Cons next alloca start createIOContext deleteIOContext) len =
-   Unsafe.performIO $
-   bracket createIOContext (deleteIOContext . fst) $ \ (_ioContext, params) ->
-   SVB.createAndTrim len $ \ ptr ->
-      do fill <-
-            compile
-               (next $ Tuple.valueOf params) alloca (start $ Tuple.valueOf params)
-         fmap (fromIntegral :: Word -> Int) $ fill (fromIntegral len) ptr
-
-
-foreign import ccall safe "dynamic" derefStartPtr ::
-   Exec.Importer (IO (LLVM.Ptr a))
-
-foreign import ccall safe "dynamic" derefStopPtr ::
-   Exec.Importer (LLVM.Ptr a -> IO ())
-
-foreign import ccall safe "dynamic" derefChunkPtr ::
-   Exec.Importer (LLVM.Ptr stateStruct -> Word -> Ptr struct -> IO Word)
-
-
-compileChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ value,
-    Memory.C state, Memory.Struct state ~ stateStruct) =>
-   (forall r z.
-    (Tuple.Phi z) =>
-    local -> state -> MaybeCont.T r z (value, state)) ->
-   (forall r. CodeGenFunction r local) ->
-   (forall r. CodeGenFunction r state) ->
-   IO (IO (LLVM.Ptr stateStruct),
-       Exec.Finalizer stateStruct,
-       LLVM.Ptr stateStruct -> Word -> Ptr a -> IO Word)
-compileChunky next alloca start =
-   Exec.compile "signal-chunky" $
-      liftA3 (,,)
-         (Exec.createFunction derefStartPtr "startsignal" $
-          do
-             pptr <- LLVM.malloc
-             flip Memory.store pptr =<< start
-             ret pptr)
-{- for debugging: allocation with initialization makes type inference difficult
-         (Exec.createFunPtr "startsignal" $
-          do
-             pptr <- malloc
-             let retn :: CodeGenFunction r state -> Value (Ptr state) -> CodeGenFunction (Ptr state) ()
-                 retn _ ptr = ret ptr
-             retn undefined pptr)
--}
-         (Exec.createFinalizer derefStopPtr "stopsignal" $
-          \ pptr -> LLVM.free pptr >> ret ())
-         (Exec.createFunction derefChunkPtr "fillsignal" $
-          \ sptr loopLen ptr -> do
-             sInit <- Memory.load sptr
-             local <- alloca
-             (pos,sExit) <-
-                Storable.arrayLoopMaybeCont loopLen ptr sInit $
-                   \ ptri s0 -> do
-                (y,s1) <- next local s0
-                MaybeCont.lift $ Storable.store y ptri
-                return s1
-             Memory.store (Maybe.fromJust sExit) sptr
-             ret pos)
-
-
-runChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   T value -> SVL.ChunkSize -> IO (SVL.Vector a)
-runChunky (Cons next alloca start createIOContext deleteIOContext)
-      (SVL.ChunkSize size) = do
-   (ioContext, params) <- createIOContext
-   (startFunc, stopFunc, fill) <-
-      compileChunky
-         (next $ Tuple.valueOf params) alloca (start $ Tuple.valueOf params)
-
-   statePtr <- ForeignPtr.newInit stopFunc startFunc
-   ioContextPtr <- ForeignPtr.newAux (deleteIOContext ioContext)
-
-   let go =
-         Unsafe.interleaveIO $ do
-            v <-
-               ForeignPtr.with statePtr $ \sptr ->
-               SVB.createAndTrim size $
-               fmap (fromIntegral :: Word -> Int) .
-               fill sptr (fromIntegral size)
-            touchForeignPtr ioContextPtr
-            (if SV.length v > 0
-               then fmap (v:)
-               else id) $
-               (if SV.length v < size
-                  then return []
-                  else go)
-   fmap SVL.fromChunks go
-
-renderChunky ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
-   SVL.ChunkSize -> T value -> SVL.Vector a
-renderChunky size sig =
-   Unsafe.performIO (runChunky sig size)
diff --git a/src/Synthesizer/LLVM/Simple/SignalPacked.hs b/src/Synthesizer/LLVM/Simple/SignalPacked.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Simple/SignalPacked.hs
+++ /dev/null
@@ -1,166 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-module Synthesizer.LLVM.Simple.SignalPacked where
-
-import Synthesizer.LLVM.Simple.SignalPrivate (Core(Core), alter)
-import qualified Synthesizer.LLVM.Simple.Signal as Sig
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.MaybeContinuation as Maybe
-import qualified LLVM.Extra.Control as U
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (valueOf)
-
-import qualified Control.Monad.Trans.Class as MT
-import qualified Control.Monad.Trans.State as MS
-import Control.Monad (replicateM)
-
-import Data.Word (Word)
-
-import NumericPrelude.Numeric as NP
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith)
-
-
-
-{- |
-Convert a signal of scalar values into one using processor vectors.
-If the signal length is not divisible by the chunk size,
-then the last chunk is dropped.
--}
-pack, packRotate ::
-   (Sig.C signal, Serial.C v, a ~ Serial.Element v) =>
-   signal a -> signal v
-pack = packRotate
-
-packRotate = alter (\(Core next start stop) -> Core
-   (\param s -> do
-      wInit <- Maybe.lift $ Serial.writeStart
-      (w2,_,s2) <-
-         Maybe.fromBool $
-         U.whileLoop
-            (valueOf True,
-             (wInit,
-              valueOf $ (fromIntegral $ Serial.sizeOfIterator wInit :: Word),
-              s))
-            (\(cont,(_w0,i0,_s0)) ->
-               A.and cont =<<
-                  A.cmp LLVM.CmpGT i0 A.zero)
-            (\(_,(w0,i0,s0)) -> Maybe.toBool $ do
-               (a,s1) <- next param s0
-               Maybe.lift $ do
-                  w1 <- Serial.writeNext a w0
-                  i1 <- A.dec i0
-                  return (w1,i1,s1))
-      v <- Maybe.lift $ Serial.writeStop w2
-      return (v, s2))
-   start
-   stop)
-
-{-
-We could reformulate it in terms of WriteIterator
-that accesses elements using LLVM.extract.
-We might move the loop counter into the Iterator,
-but we have to assert that the counter is not duplicated.
-
-packIndex ::
-   (Sig.C signal, Serial.C v, a ~ Serial.Element v) =>
-   signal a -> signal v
-packIndex = alter (\(Core next start stop) -> Core
-   (\param s -> do
-      (v2,_,s2) <-
-         Maybe.fromBool $
-         U.whileLoop
-            (valueOf True, (Tuple.undef, A.zero, s))
-            (\(cont,(v0,i0,_s0)) ->
-               A.and cont =<<
-                  A.cmp LLVM.CmpLT i0
-                     (valueOf $ fromIntegral $ Serial.size v0))
-            (\(_,(v0,i0,s0)) -> Maybe.toBool $ do
-               (a,s1) <- next param s0
-               Maybe.lift $ do
-                  v1 <- Vector.insert i0 a v0
-                  i1 <- A.inc i0
-                  return (v1,i1,s1))
-      return (v2, s2))
-   start
-   stop)
--}
-
-
-{- |
-Like 'pack' but duplicates the code for creating elements.
-That is, for vectors of size n, the code of the input signal
-will be emitted n times.
-This is efficient only for simple input generators.
--}
-packSmall ::
-   (Sig.C signal, Serial.C v, a ~ Serial.Element v) =>
-   signal a -> signal v
-packSmall = alter (\(Core next start stop) -> Core
-   (\param ->
-      MS.runStateT $
-      Serial.withSize $ \n ->
-         MT.lift . Maybe.lift . Serial.assemble
-         =<<
-         replicateM n (MS.StateT $ next param))
-   start
-   stop)
-
-
-unpack, unpackRotate ::
-   (Sig.C signal,
-    Serial.Read v, a ~ Serial.Element v, Serial.ReadIt v ~ itv, Memory.C itv) =>
-   signal v -> signal a
-unpack = unpackRotate
-
-unpackRotate = alter (\(Core next start stop) -> Core
-   (\context (i0,r0,s0) -> do
-      endOfVector <-
-         Maybe.lift $ A.cmp LLVM.CmpEQ i0 (valueOf (0::Word))
-      (i2,r2,s2) <-
-         Maybe.fromBool $
-         U.ifThen endOfVector (valueOf True, (i0,r0,s0)) $ do
-            (cont1, (v1,s1)) <- Maybe.toBool $ next context s0
-            r1 <- Serial.readStart v1
-            return (cont1, (valueOf $ fromIntegral $ Serial.size v1, r1, s1))
-      Maybe.lift $ do
-         (a,r3) <- Serial.readNext r2
-         i3 <- A.dec i2
-         return (a, (i3,r3,s2)))
-   (fmap (\s -> (A.zero, Tuple.undef, s)) . start)
-   (\(_,_,state) -> stop state))
-
-
-{-
-We could reformulate it in terms of ReadIterator
-that accesses elements using LLVM.extract.
-We might move the loop counter into the Iterator,
-but we have to assert that the counter is not duplicated.
-
-unpackIndex ::
-   (Serial.C v, a ~ Serial.Element v, Memory.C v) =>
-   signal v -> signal a
-unpackIndex = alter (\(Core next start stop) -> Core
-   (\param (i0,v0,s0) -> do
-      endOfVector <-
-         Maybe.lift $ A.cmp LLVM.CmpGE i0
-            (valueOf $ fromIntegral $ Serial.size v0)
-      (i2,v2,s2) <-
-         Maybe.fromBool $
-         U.ifThen endOfVector (valueOf True, (i0,v0,s0)) $ do
-            (cont1, (v1,s1)) <- Maybe.toBool $ next param s0
-            return (cont1, (A.zero, v1, s1))
-      Maybe.lift $ do
-         a <- Vector.extract i2 v2
-         i3 <- A.inc i2
-         return (a, (i3,v2,s2)))
-   (\p -> do
-      s <- start p
-      let v = Tuple.undef
-      return (valueOf $ fromIntegral $ Serial.size v, v, s))
-   stop)
--}
diff --git a/src/Synthesizer/LLVM/Simple/SignalPrivate.hs b/src/Synthesizer/LLVM/Simple/SignalPrivate.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Simple/SignalPrivate.hs
+++ /dev/null
@@ -1,340 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE Rank2Types #-}
-module Synthesizer.LLVM.Simple.SignalPrivate where
-
-import qualified Synthesizer.LLVM.Storable.ChunkIterator as ChunkIt
-
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.MaybeContinuation as MaybeCont
-import qualified LLVM.Extra.Either as Either
-import qualified LLVM.Extra.Maybe as Maybe
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-import LLVM.Extra.Control (ifThen)
-
-import qualified LLVM.Util.Proxy as LP
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value, valueOf)
-
-import Control.Monad (liftM2)
-import Control.Applicative (Applicative, pure, liftA2, (<*>), (<$>))
-
-import Foreign.StablePtr (StablePtr)
-import Foreign.Ptr (Ptr, nullPtr)
-
-import Data.Tuple.Strict (zipPair)
-import Data.Monoid (Monoid, mempty, mappend)
-import Data.Semigroup (Semigroup, (<>))
-import Data.Word (Word)
-
-import qualified Number.Ratio as Ratio
-import qualified Algebra.Field as Field
-import qualified Algebra.Ring as Ring
-import qualified Algebra.Additive as Additive
-
-import NumericPrelude.Base hiding (and, iterate, map, zip, zipWith)
-
-import qualified Prelude as P
-
-
-{-
-We need the forall quantification for 'CodeGenFunction's @r@ parameter.
-This type parameter will be unified with the result type of the final function.
-Since one piece of code can be used in multiple functions
-we cannot yet fix the type @r@ here.
-
-
-We might avoid code duplication with Causal.Process by defining
-
-> newtype T a = Cons (Causal.T () a)
-
-
-In earlier versions the createIOContext method created only an ioContext
-that was directly used to construct code for 'start' and 'next'.
-This had the advantage that we did not need to pass
-something via the Memory.C interface to the function.
-However, creating both an ioContext and a low-level parameter has those advantages:
-We can design Causal.Process such that a process
-can be applied to multiple signals without recompilation.
-We can lift simple signals and processes to their parameterized counterparts.
--}
-data T a =
-   forall state local ioContext parameters.
-      (Marshal.C parameters, Memory.C state) =>
-      Cons (forall r c.
-            (Tuple.Phi c) =>
-            Tuple.ValueOf parameters -> local ->
-            state -> MaybeCont.T r c (a, state))
-               -- compute next value
-           (forall r.
-            CodeGenFunction r local)
-               -- allocate temporary variables before a loop
-           (forall r.
-            Tuple.ValueOf parameters ->
-            CodeGenFunction r state)
-               -- initial state
-           (IO (ioContext, parameters))
-               {- initialization from IO monad
-               This will be run within Unsafe.performIO,
-               so no observable In/Out actions please!
-               -}
-           (ioContext -> IO ())
-               -- finalization from IO monad, also run within Unsafe.performIO
-
-
-data Core context initState exitState a =
-   forall state.
-      (Memory.C state) =>
-      Core (forall r c.
-            (Tuple.Phi c) =>
-            context ->
-            state -> MaybeCont.T r c (a, state))
-               -- compute next value
-           (forall r.
-            initState ->
-            CodeGenFunction r state)
-               -- initial state
-           (state -> exitState)
-               -- extract final state for cleanup
-
-
-class Applicative signal => C signal where
-   simple ::
-      (Memory.C state) =>
-      (forall r c. state -> MaybeCont.T r c (a, state)) ->
-      (forall r. CodeGenFunction r state) ->
-      signal a
-   simple next start =
-      simpleAlloca (\() state -> next state) (return ()) start
-
-   simpleAlloca ::
-      (Memory.C state) =>
-      (forall r c. local -> state -> MaybeCont.T r c (a, state)) ->
-      (forall r. CodeGenFunction r local) ->
-      (forall r. CodeGenFunction r state) ->
-      signal a
-
-   alter ::
-      (forall contextLocal initState exitState.
-          Core contextLocal initState exitState a0 ->
-          Core contextLocal initState exitState a1) ->
-      signal a0 -> signal a1
-
-instance C T where
-   simpleAlloca next alloca0 start =
-      Cons
-         (\() local -> next local)
-         alloca0
-         (const start)
-         (return ((),()))
-         (const $ return ())
-
-   alter f (Cons next0 alloca0 start0 create delete) =
-      case f (Core (uncurry next0) start0 id) of
-         Core next1 start1 _ ->
-            Cons (curry next1) alloca0 start1 create delete
-
-
-map ::
-   (C signal) =>
-   (forall r. a -> CodeGenFunction r b) -> signal a -> signal b
-map f = alter (\(Core next start stop) ->
-   Core
-      (\ioContext sa0 -> do
-         (a,sa1) <- next ioContext sa0
-         b <- MaybeCont.lift $ f a
-         return (b, sa1))
-      start
-      stop)
-
-zipWith ::
-   (C signal) =>
-   (forall r. a -> b -> CodeGenFunction r c) ->
-   signal a -> signal b -> signal c
-zipWith f a b  =  map (uncurry f) $ liftA2 (,) a b
-
-
-zip :: T a -> T b -> T (a,b)
-zip (Cons nextA allocaA startA createIOContextA deleteIOContextA)
-    (Cons nextB allocaB startB createIOContextB deleteIOContextB) =
-   Cons
-      (\(paramA, paramB) (localA, localB) (sa0,sb0) ->
-         liftM2 zipPair
-            (nextA paramA localA sa0)
-            (nextB paramB localB sb0))
-      (liftM2 (,) allocaA allocaB)
-      (combineStart startA startB)
-      (combineCreate createIOContextA createIOContextB)
-      (combineDelete deleteIOContextA deleteIOContextB)
-
-combineStart ::
-   Monad m =>
-   (paramA -> m stateA) ->
-   (paramB -> m stateB) ->
-   (paramA, paramB) -> m (stateA, stateB)
-combineStart startA startB (paramA, paramB) =
-   liftM2 (,) (startA paramA) (startB paramB)
-
-combineCreate ::
-   Monad m =>
-   m (ioContextA, contextA) ->
-   m (ioContextB, contextB) ->
-   m ((ioContextA, ioContextB), (contextA, contextB))
-combineCreate createIOContextA createIOContextB =
-   liftM2 zipPair createIOContextA createIOContextB
-
-combineDelete :: (Monad m) => (ca -> m ()) -> (cb -> m ()) -> (ca, cb) -> m ()
-combineDelete deleteIOContextA deleteIOContextB (ca,cb) =
-   deleteIOContextA ca >> deleteIOContextB cb
-
-
-instance Functor T where
-   fmap f = map (return . f)
-
-{- |
-ZipList semantics
--}
-instance Applicative T where
-   pure x = simple (\() -> return (x, ())) (return ())
-   f <*> a = fmap (uncurry ($)) $ zip f a
-
-instance (A.Additive a) => Additive.C (T a) where
-   zero = pure A.zero
-   negate = map A.neg
-   (+) = zipWith A.add
-   (-) = zipWith A.sub
-
-instance (A.PseudoRing a, A.IntegerConstant a) => Ring.C (T a) where
-   one = pure A.one
-   fromInteger n = pure (A.fromInteger' n)
-   (*) = zipWith A.mul
-
-instance (A.Field a, A.RationalConstant a) => Field.C (T a) where
-   fromRational' x = pure (A.fromRational' $ Ratio.toRational98 x)
-   (/) = zipWith A.fdiv
-
-
-instance (A.PseudoRing a, A.Real a, A.IntegerConstant a) => P.Num (T a) where
-   fromInteger n = pure (A.fromInteger' n)
-   negate = map A.neg
-   (+) = zipWith A.add
-   (-) = zipWith A.sub
-   (*) = zipWith A.mul
-   abs = map A.abs
-   signum = map A.signum
-
-instance (A.Field a, A.Real a, A.RationalConstant a) => P.Fractional (T a) where
-   fromRational x = pure (A.fromRational' x)
-   (/) = zipWith A.fdiv
-
-
-
-empty :: (C signal) => signal a
-empty = simple (const $ MaybeCont.nothing) (return ())
-
-{- |
-Appending many signals is inefficient,
-since in cascadingly appended signals the parts are counted in an unary way.
-Concatenating infinitely many signals is impossible.
-If you want to concatenate a lot of signals,
-please render them to lazy storable vectors first.
--}
-{-
-We might save a little space by using a union
-for the states of the first and the second signal generator.
-If the concatenated generators allocate memory,
-we could also save some memory by calling @startB@
-only after the first generator finished.
-However, for correct deallocation
-we would need to track which of the @start@ blocks
-have been executed so far.
-This in turn might be difficult in connection with the garbage collector.
--}
-append :: (Tuple.Phi a, Tuple.Undefined a) => T a -> T a -> T a
-append
-      (Cons nextA allocaA startA createIOContextA deleteIOContextA)
-      (Cons nextB allocaB startB createIOContextB deleteIOContextB) =
-   Cons
-      (\(parameterA, parameterB) (localA, localB) es0 ->
-            MaybeCont.fromMaybe $ do
-         es1 <-
-            Either.run es0
-               (\sa0 ->
-                  MaybeCont.resolve
-                     (nextA parameterA localA sa0)
-                     (fmap Either.right $ startB parameterB)
-                     (\(a1,sa1) -> return (Either.left (a1, sa1))))
-               (return . Either.right)
-
-         Either.run es1
-            (\(a1,s1) -> return (Maybe.just (a1, Either.left s1)))
-            (\sb0 ->
-               MaybeCont.toMaybe $
-               fmap (\(b,sb1) -> (b, Either.right sb1)) $
-               nextB parameterB localB sb0))
-      (liftM2 (,) allocaA allocaB)
-      (\(parameterA, _parameterB) -> Either.left <$> startA parameterA)
-      (combineCreate createIOContextA createIOContextB)
-      (combineDelete deleteIOContextA deleteIOContextB)
-
-instance (Tuple.Phi a, Tuple.Undefined a) => Semigroup (T a) where
-   (<>) = append
-
-instance (Tuple.Phi a, Tuple.Undefined a) => Monoid (T a) where
-   mempty = empty
-   mappend = append
-
-
-
-storableVectorNextChunk ::
-   (Tuple.Phi c, Storable.C a) =>
-   String ->
-   Value (StablePtr (ChunkIt.T a)) -> Value (LLVM.Ptr Word) -> () ->
-   MaybeCont.T r c ((Value (Ptr a), Value Word), ())
-storableVectorNextChunk callbackName stable lenPtr () =
-   MaybeCont.fromBool $ do
-      nextChunkFn <- LLVM.staticNamedFunction callbackName ChunkIt.nextCallBack
-      (buffer,len) <-
-         liftM2 (,)
-            (LLVM.call nextChunkFn stable lenPtr)
-            (LLVM.load lenPtr)
-      valid <- A.cmp LLVM.CmpNE buffer (valueOf nullPtr)
-      return (valid, ((buffer,len), ()))
-
-flattenChunks ::
-   (C signal, Storable.C a, Tuple.ValueOf a ~ value) =>
-   signal (Value (Ptr a), Value Word) -> signal value
-flattenChunks = alter $ \(Core next start stop) ->
-   Core
-      (\context ((buffer0,length0), state0) -> do
-         ((buffer1,length1), state1) <- MaybeCont.fromBool $ do
-            needNext <- A.cmp LLVM.CmpEQ length0 A.zero
-            ifThen needNext
-               (valueOf True, ((buffer0,length0), state0))
-               (MaybeCont.toBool $ next context state0)
-         MaybeCont.lift $ do
-            x <- Storable.load buffer1
-            buffer2 <- Storable.incrementPtr buffer1
-            length2 <- A.dec length1
-            return (x, ((buffer2,length2), state1)))
-      (\p -> (,) (valueOf nullPtr, A.zero) <$> start p)
-      (stop . snd)
-
-alloca :: (C signal, LLVM.IsSized a) => signal (LLVM.Value (LLVM.Ptr a))
-alloca =
-   simpleAlloca
-      (\ptr () -> return (ptr, ()))
-      LLVM.alloca
-      (return ())
-
-
-proxyFromElement :: f a -> LP.Proxy a
-proxyFromElement _ = LP.Proxy
-
-proxyFromElement2 :: f (g a) -> LP.Proxy a
-proxyFromElement2 _ = LP.Proxy
diff --git a/src/Synthesizer/LLVM/Simple/Value.hs b/src/Synthesizer/LLVM/Simple/Value.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Simple/Value.hs
+++ /dev/null
@@ -1,569 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE UndecidableInstances #-}
-module Synthesizer.LLVM.Simple.Value (
-   T, decons,
-   twoPi, square, sqrt,
-   max, min, limit, fraction,
-
-   (%==), (%/=), (%<), (%<=), (%>), (%>=), not,
-   (%&&), (%||),
-   (?), (??),
-
-   lift0, lift1, lift2, lift3,
-   unlift0, unlift1, unlift2, unlift3, unlift4, unlift5,
-   constantValue, constant,
-   fromInteger', fromRational',
-
-   Flatten(flattenCode, unfoldCode), Registers,
-   flatten, unfold,
-   flattenCodeTraversable, unfoldCodeTraversable,
-   flattenFunction,
-   ) where
-
-import qualified LLVM.Extra.Control as C
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-
-import LLVM.Core (CodeGenFunction)
-import qualified LLVM.Core as LLVM
-
-import qualified Synthesizer.Basic.Phase as Phase
-
-import qualified Data.Vault.Lazy as Vault
-import qualified Control.Monad.Trans.Class as MT
-import qualified Control.Monad.Trans.State as MS
-import Control.Monad (liftM2, liftM3)
-import Control.Applicative (Applicative, pure, (<*>))
-import Control.Functor.HT (unzip, unzip3)
-
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
-
--- import qualified Algebra.NormedSpace.Maximum   as NormedMax
-import qualified Algebra.NormedSpace.Euclidean as NormedEuc
-import qualified Algebra.NormedSpace.Sum       as NormedSum
-
-import qualified Algebra.Transcendental as Trans
-import qualified Algebra.Algebraic as Algebraic
-import qualified Algebra.RealRing as RealRing
-import qualified Algebra.Absolute as Absolute
-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 qualified Number.Complex as Complex
-
-import qualified Data.Traversable as Trav
-import qualified Data.Foldable as Fold
-
-import qualified System.Unsafe as Unsafe
-
-import qualified Prelude as P
-import NumericPrelude.Numeric hiding (pi, sqrt, fromRational', fraction)
-import NumericPrelude.Base hiding (min, max, unzip, unzip3, not)
-
-
-{-
-The @r@ type parameter must be hidden and forall-quantified
-because otherwise we would need an impossible type
-where we have to quantify for @r@ and @t@ in different scopes
-while having a class constraint that involves both of them.
-
-> osci ::
->    (RealRing.C (Value.T r t),
->     IsFirstClass t, IsFloating t,
->     IsPrimitive t, IsConst t) =>
->    (forall r. Wave.T (Value.T r t) (Value.T r y)) ->
->    t -> t -> T (Value y)
-
--}
-newtype T a = Cons {code :: forall r. Compute r a}
-
-decons :: T a -> (forall r. LLVM.CodeGenFunction r a)
-decons value =
-   MS.evalStateT (code value) Vault.empty
-
-instance Functor T where
-   fmap f x = consUnique (fmap f (code x))
-
-instance Applicative T where
-   pure = constantValue
-   f <*> x = consUnique (code f <*> code x)
-
-
-type Compute r a =
-   MS.StateT Vault.Vault (LLVM.CodeGenFunction r) a
-
-consUnique :: (forall r. Compute r a) -> T a
-consUnique code0 =
-   Unsafe.performIO $
-   fmap (consKey code0) Vault.newKey
-
-consKey :: (forall r. Compute r a) -> Vault.Key a -> T a
-consKey code0 key =
-   Cons (do
-      ma <- MS.gets (Vault.lookup key)
-      case ma of
-         Just a -> return a
-         Nothing -> do
-            a <- code0
-            MS.modify (Vault.insert key a)
-            return a)
-
-{- |
-We do not require a numeric prelude superclass,
-thus also LLVM only types like vectors are instances.
--}
-instance (A.Additive a) => Additive.C (T a) where
-   zero = constantValue A.zero
-   (+) = lift2 A.add
-   (-) = lift2 A.sub
-   negate = lift1 A.neg
-
-instance (A.PseudoRing a, A.IntegerConstant a) =>
-      Ring.C (T a) where
-   one = constantValue A.one
-   (*) = lift2 A.mul
-   fromInteger = fromInteger'
-
-{-
-This instance is enough for Module here.
-The difference to Module instances on Haskell tuples is,
-that LLVM vectors cannot be nested.
--}
-instance (a ~ A.Scalar v, A.PseudoModule v, A.IntegerConstant a) =>
-      Module.C (T a) (T v) where
-   (*>) = lift2 A.scale
-
-instance (A.Additive a, A.IntegerConstant a) => Enum (T a) where
-   succ x = x + constantValue A.one
-   pred x = x - constantValue A.one
-   fromEnum _ = error "CodeGenFunction Value: fromEnum"
-   toEnum = constantValue . A.fromInteger' . fromIntegral
-
-{-
-instance (IsArithmetic a, Cmp a b, Num a, IsConst a) => Real (T a) where
-   toRational _ = error "CodeGenFunction Value: toRational"
-
-instance (Cmp a b, Num a, IsConst a, IsInteger a) => Integral (T a) where
-   quot = lift2 idiv
-   rem  = lift2 irem
-   quotRem x y = (quot x y, rem x y)
-   toInteger _ = error "CodeGenFunction Value: toInteger"
--}
-
-instance (A.Field a, A.RationalConstant a) => Field.C (T a) where
-   (/) = lift2 A.fdiv
-   fromRational' = fromRational' . Field.fromRational'
-
-{-
-instance (Cmp a b, Fractional a, IsConst a, IsFloating a) => RealFrac (T a) where
-   properFraction _ = error "CodeGenFunction Value: properFraction"
--}
-
-instance (A.Transcendental a, A.RationalConstant a) => Algebraic.C (T a) where
-   sqrt = lift1 A.sqrt
-   root n x = lift2 A.pow x (1 / fromInteger n)
-   x^/r = lift2 A.pow x (Field.fromRational' r)
-
-instance (A.Transcendental a, A.RationalConstant a) => Trans.C (T a) where
-   pi = lift0 A.pi
-   sin = lift1 A.sin
-   cos = lift1 A.cos
-   (**) = lift2 A.pow
-   exp = lift1 A.exp
-   log = lift1 A.log
-
-   asin _ = error "LLVM missing intrinsic: asin"
-   acos _ = error "LLVM missing intrinsic: acos"
-   atan _ = error "LLVM missing intrinsic: atan"
-
-
-instance
-   (A.PseudoRing a, A.Real a, A.IntegerConstant a) =>
-      P.Num (T a) where
-   fromInteger = fromInteger'
-   (+) = lift2 A.add
-   (-) = lift2 A.sub
-   (*) = lift2 A.mul
-   negate = lift1 A.neg
-   abs = lift1 A.abs
-   signum = lift1 A.signum
-
-instance
-   (A.Field a, A.Real a, A.RationalConstant a) =>
-      P.Fractional (T a) where
-   fromRational = fromRational'
-   (/) = lift2 A.fdiv
-
-instance
-   (A.Transcendental a, A.Real a, A.RationalConstant a) =>
-      P.Floating (T a) where
-   pi = lift0 A.pi
-   sin = lift1 A.sin
-   cos = lift1 A.cos
-   (**) = lift2 A.pow
-   exp = lift1 A.exp
-   log = lift1 A.log
-
-   asin _ = error "LLVM missing intrinsic: asin"
-   acos _ = error "LLVM missing intrinsic: acos"
-   atan _ = error "LLVM missing intrinsic: atan"
-
-   sinh x  = (exp x - exp (-x)) / 2
-   cosh x  = (exp x + exp (-x)) / 2
-   asinh x = log (x + sqrt (x*x + 1))
-   acosh x = log (x + sqrt (x*x - 1))
-   atanh x = (log (1 + x) - log (1 - x)) / 2
-
-
-twoPi ::
-   (A.Transcendental a, A.RationalConstant a) =>
-   T a
-twoPi = 2 * Trans.pi
-
-square ::
-   (A.PseudoRing a) =>
-   T a -> T a
-square = lift1 A.square
-
-{- |
-The same as 'Algebraic.sqrt',
-but needs only Algebraic constraint, not Transcendental.
--}
-sqrt ::
-   (A.Algebraic a) =>
-   T a -> T a
-sqrt = lift1 A.sqrt
-
-
-min, max :: (A.Real a) => T a -> T a -> T a
-min = lift2 A.min
-max = lift2 A.max
-
-limit :: (A.Real a) => (T a, T a) -> T a -> T a
-limit (l,u) = max l . min u
-
-fraction :: (A.Fraction a) => T a -> T a
-fraction = lift1 A.fraction
-
-
-instance (A.Real a, A.PseudoRing a, A.IntegerConstant a) =>
-      Absolute.C (T a) where
-   abs = lift1 A.abs
-   signum = lift1 A.signum
-
-{-
-For useful instances with different scalar and vector type,
-we would need a more flexible superclass.
--}
-instance (A.Real a, A.IntegerConstant a, a ~ A.Scalar a, A.PseudoModule a) =>
-      NormedSum.C (T a) (T a) where
-   norm = lift1 A.abs
-
-instance (A.Real a, A.IntegerConstant a, a ~ A.Scalar a, A.PseudoModule a) =>
-      NormedEuc.Sqr (T a) (T a) where
-   normSqr = lift1 A.square
-
-instance
-   (NormedEuc.Sqr (T a) (T v),
-    A.RationalConstant a, A.Algebraic a) =>
-      NormedEuc.C (T a) (T v) where
-   norm = lift1 A.sqrt . NormedEuc.normSqr
-
-{-
-instance (A.Real a, A.IntegerConstant a, A.PseudoModule a a) =>
-      NormedMax.C (T a) (T a) where
-   norm = lift1 A.abs
--}
-
-
-infix  4  %==, %/=, %<, %<=, %>=, %>
-
-(%==), (%/=), (%<), (%<=), (%>), (%>=) ::
-   (LLVM.CmpRet a) =>
-   T (LLVM.Value a) -> T (LLVM.Value a) -> T (LLVM.Value (LLVM.CmpResult a))
-(%==) = lift2 $ LLVM.cmp LLVM.CmpEQ
-(%/=) = lift2 $ LLVM.cmp LLVM.CmpNE
-(%>)  = lift2 $ LLVM.cmp LLVM.CmpGT
-(%>=) = lift2 $ LLVM.cmp LLVM.CmpGE
-(%<)  = lift2 $ LLVM.cmp LLVM.CmpLT
-(%<=) = lift2 $ LLVM.cmp LLVM.CmpLE
-
-infixr 3  %&&
-infixr 2  %||
-
--- | Lazy AND
-(%&&) :: T (LLVM.Value Bool) -> T (LLVM.Value Bool) -> T (LLVM.Value Bool)
-a %&& b = a ? (b, constant False)
-
--- | Lazy OR
-(%||) :: T (LLVM.Value Bool) -> T (LLVM.Value Bool) -> T (LLVM.Value Bool)
-a %|| b = a ? (constant True, b)
-
-not :: T (LLVM.Value Bool) -> T (LLVM.Value Bool)
-not = lift1 LLVM.inv
-
-
-infix  0 ?
-{- |
-@true ? (t,f)@ evaluates @t@,
-@false ? (t,f)@ evaluates @f@.
-@t@ and @f@ can reuse interim results,
-but they cannot contribute shared results,
-since only one of them will be run.
-Cf. '(??)'
--}
-(?) ::
-   (Flatten value, Registers value ~ a, Tuple.Phi a) =>
-   T (LLVM.Value Bool) -> (value, value) -> value
-c ? (t, f) =
-   unfoldCode $ consUnique $ do
-      b <- code c
-      shared <- MS.get
-      MT.lift $
-         C.ifThenElse b
-            (MS.evalStateT (flattenCode t) shared)
-            (MS.evalStateT (flattenCode f) shared)
-
-infix 0 ??
-{- |
-The expression @c ?? (t,f)@ evaluates both @t@ and @f@
-and selects components from @t@ and @f@ according to @c@.
-It is useful for vector values and
-for sharing @t@ or @f@ with other branches of an expression.
--}
-(??) ::
-   (LLVM.IsFirstClass a, LLVM.CmpRet a) =>
-   T (LLVM.Value (LLVM.CmpResult a)) ->
-   (T (LLVM.Value a), T (LLVM.Value a)) ->
-   T (LLVM.Value a)
-c ?? (t, f) = lift3 LLVM.select c t f
-
-
-
-lift0 ::
-   (forall r. CodeGenFunction r a) ->
-   T a
-lift0 f =
-   consUnique $ MT.lift $ f
-
-lift1 ::
-   (forall r. a -> CodeGenFunction r b) ->
-   T a -> T b
-lift1 f x =
-   consUnique $ MT.lift . f =<< code x
-
-lift2 ::
-   (forall r. a -> b -> CodeGenFunction r c) ->
-   T a -> T b -> T c
-lift2 f x y =
-   consUnique $ do
-      xv <- code x
-      yv <- code y
-      MT.lift $ f xv yv
-
-lift3 ::
-   (forall r. a -> b -> c -> CodeGenFunction r d) ->
-   T a -> T b -> T c -> T d
-lift3 f x y z =
-   consUnique $ do
-      xv <- code x
-      yv <- code y
-      zv <- code z
-      MT.lift $ f xv yv zv
-
-
-_unlift0 ::
-   T a ->
-   (forall r. CodeGenFunction r a)
-_unlift0 = decons
-
-unlift0 ::
-   (Flatten value) =>
-   value ->
-   (forall r. CodeGenFunction r (Registers value))
-unlift0 = flatten
-
-_unlift1 ::
-   (T a -> T b) ->
-   (forall r. a -> CodeGenFunction r b)
-_unlift1 = unlift1
-
-{-
-Better type inference than flattenFunction.
--}
-unlift1 ::
-   (Flatten value) =>
-   (T a -> value) ->
-   (forall r. a -> CodeGenFunction r (Registers value))
-unlift1 f a =
-   flatten (f (constantValue a))
-
-_unlift2 ::
-   (T a -> T b -> T c) ->
-   (forall r. a -> b -> CodeGenFunction r c)
-_unlift2 = unlift2
-
-unlift2 ::
-   (Flatten value) =>
-   (T a -> T b -> value) ->
-   (forall r. a -> b -> CodeGenFunction r (Registers value))
-unlift2 f a b =
-   flatten (f (constantValue a) (constantValue b))
-
-unlift3 ::
-   (Flatten value) =>
-   (T a -> T b -> T c -> value) ->
-   (forall r. a -> b -> c -> CodeGenFunction r (Registers value))
-unlift3 f a b c =
-   flatten (f (constantValue a) (constantValue b) (constantValue c))
-
-unlift4 ::
-   (Flatten value) =>
-   (T a -> T b -> T c -> T d -> value) ->
-   (forall r. a -> b -> c -> d -> CodeGenFunction r (Registers value))
-unlift4 f a b c d =
-   flatten $
-   f (constantValue a) (constantValue b) (constantValue c) (constantValue d)
-
-unlift5 ::
-   (Flatten value) =>
-   (T a -> T b -> T c -> T d -> T e -> value) ->
-   (forall r. a -> b -> c -> d -> e -> CodeGenFunction r (Registers value))
-unlift5 f a b c d e =
-   flatten $
-   f (constantValue a) (constantValue b) (constantValue c)
-      (constantValue d) (constantValue e)
-
-
-constantValue :: a -> T a
-constantValue x =
-   consUnique (return x)
-
-constant :: (LLVM.IsConst a) => a -> T (LLVM.Value a)
-constant = constantValue . LLVM.valueOf
-
-fromInteger' :: (A.IntegerConstant a) => Integer -> T a
-fromInteger' = constantValue . A.fromInteger'
-
-fromRational' :: (A.RationalConstant a) => P.Rational -> T a
-fromRational' = constantValue . A.fromRational'
-
-
-class Flatten value where
-   type Registers value :: *
-   flattenCode :: value -> Compute r (Registers value)
-   unfoldCode :: T (Registers value) -> value
-
-flatten ::
-   (Flatten value) =>
-   value -> CodeGenFunction r (Registers value)
-flatten x = MS.evalStateT (flattenCode x) Vault.empty
-
-unfold ::
-   (Flatten value) =>
-   (Registers value) -> value
-unfold x = unfoldCode $ pure x
-
-flattenCodeTraversable ::
-   (Flatten value, Trav.Traversable f) =>
-   f value -> Compute r (f (Registers value))
-flattenCodeTraversable =
-   Trav.mapM flattenCode
-
-unfoldCodeTraversable ::
-   (Flatten value, Trav.Traversable f, Applicative f) =>
-   T (f (Registers value)) -> f value
-unfoldCodeTraversable =
-   unfoldFromGetters getters
-
-unfoldFromGetters ::
-   (Functor f, Flatten b) =>
-   f (a -> Registers b) -> T a -> f b
-unfoldFromGetters g x =
-   fmap (unfoldCode . flip fmap x) g
-
-getters ::
-   (Trav.Traversable f, Applicative f) =>
-   f (f a -> a)
-getters =
-   fmap (\n x -> Fold.toList x !! n) $
-   MS.evalState (Trav.sequenceA (pure (MS.state $ \n -> (n, succ n)))) 0
-
-
-flattenFunction ::
-   (Flatten a, Flatten b) =>
-   (a -> b) -> (Registers a -> CodeGenFunction r (Registers b))
-flattenFunction f =
-   flatten . f . unfold
-
-{-
-This function is hardly useful,
-since most functions are not of type
-@(Registers a -> (forall r. CodeGenFunction r (Registers b)))@
-but of type
-@(forall r. Registers a -> CodeGenFunction r (Registers b))@.
-We would also need a method unfoldF.
-See ValueUnfoldF for some implementations.
-
-unfoldFunction ::
-   (Flatten a, Flatten b) =>
-   (Registers a -> (forall r. CodeGenFunction r (Registers b))) -> (a -> b)
-unfoldFunction f x =
-   unfoldF (f =<< flatten x)
--}
-
-
-instance (Flatten a, Flatten b) => Flatten (a,b) where
-   type Registers (a,b) = (Registers a, Registers b)
-   flattenCode (a,b) =
-      liftM2 (,) (flattenCode a) (flattenCode b)
-   unfoldCode x =
-      case unzip x of
-         (a,b) -> (unfoldCode a, unfoldCode b)
-
-instance (Flatten a, Flatten b, Flatten c) => Flatten (a,b,c) where
-   type Registers (a,b,c) = (Registers a, Registers b, Registers c)
-   flattenCode (a,b,c) =
-      liftM3 (,,) (flattenCode a) (flattenCode b) (flattenCode c)
-   unfoldCode x =
-      case unzip3 x of
-         (a,b,c) -> (unfoldCode a, unfoldCode b, unfoldCode c)
-
-instance Flatten a => Flatten (Stereo.T a) where
-   type Registers (Stereo.T a) = Stereo.T (Registers a)
-   flattenCode = flattenCodeTraversable
-   unfoldCode = unfoldCodeTraversable
-
-instance Flatten a => Flatten (Complex.T a) where
-   type Registers (Complex.T a) = Complex.T (Registers a)
-   flattenCode s =
-      liftM2 (Complex.+:)
-         (flattenCode $ Complex.real s)
-         (flattenCode $ Complex.imag s)
-   unfoldCode =
-      unfoldFromGetters $ Complex.real Complex.+: Complex.imag
-
-instance (RealRing.C a, Flatten a) => Flatten (Phase.T a) where
-   type Registers (Phase.T a) = Registers a
-   flattenCode s =
-      flattenCode $ Phase.toRepresentative s
-   unfoldCode s =
-      -- could also be unsafeFromRepresentative
-      Phase.fromRepresentative $ unfoldCode s
-
-
-instance Flatten (T a) where
-   type Registers (T a) = a
-   flattenCode = code
-   unfoldCode = id
-
-instance Flatten () where
-   type Registers () = ()
-   flattenCode = return
-   unfoldCode _ = ()
diff --git a/src/Synthesizer/LLVM/Simple/Vanilla.hs b/src/Synthesizer/LLVM/Simple/Vanilla.hs
deleted file mode 100644
--- a/src/Synthesizer/LLVM/Simple/Vanilla.hs
+++ /dev/null
@@ -1,86 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeFamilies #-}
-module Synthesizer.LLVM.Simple.Vanilla where
-
-import qualified Synthesizer.LLVM.Simple.Signal as Sig
-import qualified Synthesizer.LLVM.Simple.Value as Value
-
-import qualified Synthesizer.Basic.Phase as Phase
-import qualified Synthesizer.Basic.Wave  as Wave
-
-import qualified LLVM.Extra.MaybeContinuation as Maybe
-import qualified LLVM.Extra.ScalarOrVector as SoV
-import qualified LLVM.Extra.Memory as Memory
-import LLVM.Core (IsArithmetic, IsConst, IsFirstClass, IsSized, Value)
-
-import qualified Algebra.RealRing as RealRing
-
-import NumericPrelude.Base hiding (and, iterate, map, zipWith)
-
-
-iterateVal ::
-   (Memory.C a) =>
-   (Value.T a -> Value.T a) ->
-   Value.T a -> Sig.T (Value.T a)
-iterateVal f initial =
-   Sig.simple
-      (\y ->
-         Maybe.lift $
-         fmap (\y1 -> (Value.constantValue y, y1))
-              (Value.unlift1 f y))
-      (Value.decons initial)
-
-iterate ::
-   (Value.Flatten a, Value.Registers a ~ reg, Memory.C reg) =>
-   (a -> a) ->
-   (a -> Sig.T a)
-iterate f initial =
-   Sig.simple
-      (\y ->
-         Maybe.lift $
-         fmap (\y1 -> (Value.unfold y, y1))
-              (Value.flattenFunction f y))
-      (Value.flatten initial)
-
-
-
-map ::
-   (a -> b) ->
-   Sig.T a -> Sig.T b
-map f = Sig.map (return . f)
-
-
-osciReg ::
-   (RealRing.C tv, tv ~ Value.T (Value t),
-    SoV.Fraction t, IsConst t, IsSized t,
-    IsFirstClass y) =>
-   Wave.T (Value.T (Value t)) (Value.T (Value y)) ->
-   Value t -> Value t -> Sig.T (Value y)
-osciReg wave phase freq =
-   Sig.map
-      (Value.unlift1 $ Wave.apply wave . Phase.fromRepresentative) $
-   Sig.iterate (SoV.incPhase freq) phase
-
-osciVal ::
-   (RealRing.C tv, tv ~ Value.T (Value t),
-    SoV.Fraction t, IsConst t, IsSized t) =>
-   Wave.T (Value.T (Value t)) y ->
-   Value.T (Value t) -> Value.T (Value t) -> Sig.T y
-osciVal wave phase freq =
-   map (Wave.apply wave . Phase.fromRepresentative) $
-   iterateVal (incPhaseVal freq) phase
-
-incPhaseVal ::
-   (SoV.Fraction a, IsArithmetic a) =>
-   Value.T (Value a) -> Value.T (Value a) -> Value.T (Value a)
-incPhaseVal = Value.lift2 SoV.incPhase
-
-osci ::
-   (RealRing.C t,
-    Value.Flatten t, Value.Registers t ~ reg, Memory.C reg,
-    SoV.Fraction t, IsConst t) =>
-   Wave.T t y ->
-   Phase.T t -> t -> Sig.T y
-osci wave phase freq =
-   map (Wave.apply wave) $
-   iterate (Phase.increment freq) phase
diff --git a/src/Synthesizer/LLVM/Storable/ChunkIterator.hs b/src/Synthesizer/LLVM/Storable/ChunkIterator.hs
--- a/src/Synthesizer/LLVM/Storable/ChunkIterator.hs
+++ b/src/Synthesizer/LLVM/Storable/ChunkIterator.hs
@@ -6,11 +6,10 @@
 import qualified Data.StorableVector.Lazy as SVL
 import qualified Data.StorableVector.Base as SVB
 
-import qualified LLVM.Extra.Storable as Storable
 import qualified LLVM.Core as LLVM
 
 import Data.Word (Word)
-import Foreign.Storable (poke)
+import Foreign.Storable (Storable, poke)
 import Foreign.Ptr (FunPtr, Ptr, nullPtr)
 
 import Control.Monad (liftM2)
@@ -23,7 +22,7 @@
 FFI declarations must not have constraints.
 Thus we put them in the iterator datatype.
 -}
-data T a = (Storable.C a) => Cons (IORef [SVB.Vector a]) (IORef (SVB.Vector a))
+data T a = (Storable a) => Cons (IORef [SVB.Vector a]) (IORef (SVB.Vector a))
 
 
 foreign import ccall "&nextChunk"
@@ -33,7 +32,7 @@
    next :: StablePtr (T a) -> Ptr Word -> IO (Ptr a)
 
 
-new :: (Storable.C a) => SVL.Vector a -> IO (StablePtr (T a))
+new :: (Storable a) => SVL.Vector a -> IO (StablePtr (T a))
 new sig =
    newStablePtr =<<
    liftM2 Cons
diff --git a/src/Synthesizer/LLVM/Storable/Process.hs b/src/Synthesizer/LLVM/Storable/Process.hs
--- a/src/Synthesizer/LLVM/Storable/Process.hs
+++ b/src/Synthesizer/LLVM/Storable/Process.hs
@@ -8,10 +8,9 @@
    continuePacked,
    ) where
 
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Synthesizer.CausalIO.Process as PIO
-
 import qualified Synthesizer.Generic.Cut as CutG
 
 import qualified Data.StorableVector as SV
@@ -21,12 +20,10 @@
 import qualified Data.EventList.Relative.TimeTime  as EventListTT
 import qualified Data.EventList.Relative.TimeMixed as EventListTM
 import qualified Data.EventList.Absolute.TimeBody  as AbsEventList
-import qualified Number.NonNegative as NonNeg
 
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Core as LLVM
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
@@ -36,6 +33,8 @@
 
 import qualified System.Unsafe as Unsafe
 
+import qualified Number.NonNegative as NonNeg
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -49,7 +48,7 @@
 must fit into the length of the event list.
 -}
 makeArranger ::
-   (Arr.Arrow arrow, Storable.C a, Tuple.ValueOf a ~ value, A.Additive value) =>
+   (Arr.Arrow arrow, Storable.C a, MultiValue.Additive a) =>
    IO (arrow
           (EventListTT.T NonNeg.Int (SV.Vector a))
           (SV.Vector a))
@@ -79,10 +78,10 @@
 
 
 continuePacked ::
-   (CutG.Transform a, Storable.C b, LLVM.IsPrimitive b, TypeNum.Positive n) =>
-   PIO.T a (SV.Vector (Serial.Plain n b)) ->
-   (b -> PIO.T a (SV.Vector (Serial.Plain n b))) ->
-   PIO.T a (SV.Vector (Serial.Plain n b))
+   (CutG.Transform a, Storable.Vector b, TypeNum.Positive n) =>
+   PIO.T a (SV.Vector (Serial.T n b)) ->
+   (b -> PIO.T a (SV.Vector (Serial.T n b))) ->
+   PIO.T a (SV.Vector (Serial.T n b))
 continuePacked proc0 proc1 =
    PIO.continueChunk proc0
       (proc1 Arr.<<^ SV.last . SigStL.unpackStrict)
diff --git a/src/Synthesizer/LLVM/Storable/Signal.hs b/src/Synthesizer/LLVM/Storable/Signal.hs
--- a/src/Synthesizer/LLVM/Storable/Signal.hs
+++ b/src/Synthesizer/LLVM/Storable/Signal.hs
@@ -1,27 +1,22 @@
-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
 {- |
-Functions on lazy storable vectors that are implemented using LLVM.
+Functions on storable vectors that are implemented using LLVM.
 -}
 module Synthesizer.LLVM.Storable.Signal (
    unpackStrict, unpack,
    unpackStereoStrict, unpackStereo,
-   makeUnpackGenericStrict, makeUnpackGeneric,
    makeReversePackedStrict, makeReversePacked,
    continue, continuePacked, continuePackedGeneric,
-   -- should be moved to a private module
-   fillBuffer, makeMixer, addToBuffer,
-   makeArranger, arrange,
+   fillBuffer, makeMixer,
+   makeArranger,
    ) where
 
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
 
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 import qualified Synthesizer.LLVM.Frame.StereoInterleaved as StereoVector
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
 
 import qualified Data.StorableVector.Lazy as SVL
 import qualified Data.StorableVector as SV
@@ -33,33 +28,22 @@
 import qualified Number.NonNegative as NonNeg
 
 import qualified LLVM.DSL.Execution as Exec
-
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Memory as Memory
-import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Tuple as Tuple
-
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Core as LLVM
-import LLVM.Core (IsPrimitive, ret)
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
-import qualified Control.Category as Cat
-
-import qualified Data.List.HT as ListHT
-import Data.Word (Word)
+import Control.Monad.HT (void)
 
-import Foreign.Ptr (Ptr)
+import Foreign.Marshal.Array (advancePtr)
 import Foreign.ForeignPtr (castForeignPtr)
 import Foreign.Storable (Storable)
-import Foreign.Marshal.Array (advancePtr)
+import Foreign.Ptr (Ptr)
 
 import qualified System.Unsafe as Unsafe
 
-import NumericPrelude.Numeric
-import NumericPrelude.Base
 
-
 {- |
 This function needs only constant time
 in contrast to 'Synthesizer.LLVM.Parameterized.SignalPacked.unpack'.
@@ -68,27 +52,32 @@
 since the array size may not line up.
 It would also need copying since the source data may not be aligned properly.
 -}
-unpackStrict ::
-   (Storable.C a, IsPrimitive a, TypeNum.Positive n) =>
-   SV.Vector (Serial.Plain n a) -> SV.Vector a
-unpackStrict v =
+unpackChunk ::
+   (Storable.C a, TypeNum.Positive n) =>
+   SV.Vector (Serial.T n a) -> SV.Vector a
+unpackChunk v =
    let getDim ::
           (TypeNum.Positive n) =>
-          SV.Vector (Serial.Plain n a) -> TypeNum.Singleton n -> Int
+          SV.Vector (Serial.T n a) -> TypeNum.Singleton n -> Int
        getDim _ = TypeNum.integralFromSingleton
        d = getDim v TypeNum.singleton
        (fptr,s,l) = SVB.toForeignPtr v
    in  SVB.SV (castForeignPtr fptr) (s*d) (l*d)
 
+
+unpackStrict ::
+   (TypeNum.Positive n, Storable.Vector a) =>
+   SV.Vector (Serial.T n a) -> SV.Vector a
+unpackStrict = unpackChunk
+
 unpack ::
-   (Storable.C a, IsPrimitive a, TypeNum.Positive n) =>
-   SVL.Vector (Serial.Plain n a) -> SVL.Vector a
-unpack =
-   SVL.fromChunks . map unpackStrict . SVL.chunks
+   (TypeNum.Positive n, Storable.Vector a) =>
+   SVL.Vector (Serial.T n a) -> SVL.Vector a
+unpack = SVL.fromChunks . map unpackChunk . SVL.chunks
 
 
 unpackStereoStrict ::
-   (Storable.C a, IsPrimitive a, TypeNum.Positive n) =>
+   (TypeNum.Positive n, Storable.C a) =>
    SV.Vector (StereoVector.T n a) -> SV.Vector (Stereo.T a)
 unpackStereoStrict v =
    let getDim ::
@@ -100,67 +89,30 @@
    in  SVB.SV (castForeignPtr fptr) (s*d) (l*d)
 
 unpackStereo ::
-   (Storable.C a, IsPrimitive a, TypeNum.Positive n) =>
+   (TypeNum.Positive n, Storable.C a) =>
    SVL.Vector (StereoVector.T n a) -> SVL.Vector (Stereo.T a)
 unpackStereo =
    SVL.fromChunks . map unpackStereoStrict . SVL.chunks
 
-{- |
-This is similar to 'unpackStrict' but performs rearrangement of data.
-This is for instance necessary for stereo signals
-where the data layout of packed and unpacked data is different,
-thus simple casting of the data is not possible.
-However, for vectorized Stereo data the StereoInterleaved type
-still uses vector operations for interleaving and thus is more efficient.
--}
-makeUnpackGenericStrict ::
-   (Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,
-    Memory.C (Serial.ReadIt vv),
-    Storable.C a, Tuple.ValueOf a ~ va,
-    Storable.C v, Tuple.ValueOf v ~ vv) =>
-   IO (SV.Vector v -> SV.Vector a)
-makeUnpackGenericStrict =
-   let vectorSize ::
-          (Serial.C vl, n ~ Serial.Size vl, al ~ Serial.Element vl,
-           Storable.C v, Tuple.ValueOf v ~ vl) =>
-          SV.Vector v -> TypeNum.Singleton n
-       vectorSize _ = TypeNum.singleton
-   in  fmap (\f v -> f (TypeNum.integralFromSingleton (vectorSize v) * SV.length v) v) $
-       SigP.run (SigPS.unpack $ SigP.fromStorableVector Cat.id)
 
-makeUnpackGeneric ::
-   (Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,
-    Memory.C (Serial.ReadIt vv),
-    Storable.C a, Tuple.ValueOf a ~ va,
-    Storable.C v, Tuple.ValueOf v ~ vv) =>
-   IO (SVL.Vector v -> SVL.Vector a)
-makeUnpackGeneric =
-   fmap (\f -> SVL.fromChunks . map f . SVL.chunks) $
-   makeUnpackGenericStrict
-
-
 makeReverser ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
+   (Storable.C a, MultiValue.T a ~ value) =>
    (value -> LLVM.CodeGenFunction () value) ->
    IO (Word -> Ptr a -> Ptr a -> IO ())
---   (Memory.C a struct, Serial.C a) =>
---   IO (Word -> Ptr struct -> Ptr struct -> IO ())
 makeReverser rev =
    Exec.compile "reverse" $
    Exec.createFunction derefMixPtr "reverse" $ \ size ptrA ptrB -> do
       sizeInt <- LLVM.bitcast size
       ptrAEnd <- Storable.advancePtr sizeInt ptrA
-      _ <- Storable.arrayLoop size ptrB ptrAEnd $ \ ptrBi ptrAj0 -> do
+      void $ Storable.arrayLoop size ptrB ptrAEnd $ \ ptrBi ptrAj0 -> do
          ptrAj1 <- Storable.decrementPtr ptrAj0
          flip Storable.store ptrBi
             =<< rev
             =<< Storable.load ptrAj1
          return ptrAj1
-      ret ()
 
 makeReversePackedStrict ::
-   (Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,
-    Storable.C v, Tuple.ValueOf v ~ vv) =>
+   (TypeNum.Positive n, Storable.Vector a, v ~ Serial.T n a) =>
    IO (SV.Vector v -> SV.Vector v)
 makeReversePackedStrict = do
    rev <- makeReverser Serial.reverse
@@ -171,14 +123,14 @@
       rev (fromIntegral len) ptrA ptrB
 
 makeReversePacked ::
-   (Serial.C vv, n ~ Serial.Size vv, va ~ Serial.Element vv,
-    Storable.C v, Tuple.ValueOf v ~ vv) =>
+   (TypeNum.Positive n, Storable.Vector a, v ~ Serial.T n a) =>
    IO (SVL.Vector v -> SVL.Vector v)
 makeReversePacked =
    fmap (\f -> SVL.fromChunks . reverse . map f . SVL.chunks) $
    makeReversePackedStrict
 
 
+-- ToDo: move to synthesizer-core or storablevector
 {- |
 Append two signals where the second signal
 gets the last value of the first signal as parameter.
@@ -195,24 +147,16 @@
       (SVL.chunks x)
       (SV.switchR [] $ \_ -> SVL.chunks . y)
 
-_continueNeglectLast ::
-   (Storable a) =>
-   SVL.Vector a -> (a -> SVL.Vector a) -> SVL.Vector a
-_continueNeglectLast x y =
-   SVL.switchR SVL.empty
-      (\body l -> SVL.append body (y l)) x
-
 continuePacked ::
-   (TypeNum.Positive n, Storable.C a, IsPrimitive a) =>
-   SVL.Vector (Serial.Plain n a) ->
-   (a -> SVL.Vector (Serial.Plain n a)) ->
-   SVL.Vector (Serial.Plain n a)
+   (TypeNum.Positive n, Storable.Vector a) =>
+   SVL.Vector (Serial.T n a) ->
+   (a -> SVL.Vector (Serial.T n a)) ->
+   SVL.Vector (Serial.T n a)
 continuePacked x y =
    SVL.fromChunks $
    withLast SV.empty
       (SVL.chunks x)
-      (SV.switchR [] (\_ -> SVL.chunks . y) .
-       unpackStrict)
+      (SV.switchR [] (\_ -> SVL.chunks . y) . unpackStrict)
 
 {-
 This function reduces the last chunk to size one, repacks that
@@ -229,10 +173,6 @@
 >    return (continuePackedGeneric unpackGeneric x y)
 -}
 continuePackedGeneric ::
-{-
-   (Storable v, Serial.C v, n ~ Serial.Size v, a ~ Serial.Element v,
-    Tuple.Value v, Tuple.ValueOf v ~ vv, Memory.C vv) =>
--}
    (Storable v, Storable a) =>
    (SV.Vector v -> SV.Vector a) ->
    SVL.Vector v -> (a -> SVL.Vector v) -> SVL.Vector v
@@ -245,24 +185,14 @@
          SV.drop (SV.length lastChunk - 1) $ lastChunk)
 
 
--- candidate for utility-ht
+-- ToDo: candidate for utility-ht
 withLast :: a -> [a] -> (a -> [a]) -> [a]
 withLast deflt x y =
    foldr
       (\a cont _ -> a : cont a)
       y x deflt
 
-{-
-This version is too strict, since it looks one element ahead.
--}
-_withLast :: [a] -> (a -> [a]) -> [a]
-_withLast x y =
-   ListHT.switchR []
-      (\body end -> body ++ end : y end)
-      x
 
-
-
 foreign import ccall safe "dynamic" derefFillPtr ::
    Exec.Importer (Word -> Ptr a -> IO ())
 
@@ -271,31 +201,28 @@
 it also simplifies type inference.
 -}
 fillBuffer ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
+   (Storable.C a, MultiValue.T a ~ value) =>
    value -> IO (Word -> Ptr a -> IO ())
 fillBuffer x =
    Exec.compile "constant" $
-   Exec.createFunction derefFillPtr "constantfill" $ \ size ptr -> do
+   Exec.createFunction derefFillPtr "constantfill" $ \ size ptr ->
       Storable.arrayLoop size ptr () $ \ ptri () -> Storable.store x ptri
-      ret ()
 
 
 foreign import ccall safe "dynamic" derefMixPtr ::
    Exec.Importer (Word -> Ptr a -> Ptr a -> IO ())
 
 makeMixer ::
-   (Storable.C a, Tuple.ValueOf a ~ value) =>
+   (Storable.C a, MultiValue.T a ~ value) =>
    (value -> value -> LLVM.CodeGenFunction () value) ->
    IO (Word -> Ptr a -> Ptr a -> IO ())
 makeMixer add =
    Exec.compile "mixer" $
-   Exec.createFunction derefMixPtr "mix" $ \ size srcPtr dstPtr -> do
-      _ <-
-         Storable.arrayLoop2 size srcPtr dstPtr () $
+   Exec.createFunction derefMixPtr "mix" $ \ size srcPtr dstPtr ->
+      void $ Storable.arrayLoop2 size srcPtr dstPtr () $
             \srcPtri dstPtri () -> do
          y <- Storable.load srcPtri
          Storable.modify (add y) dstPtri
-      ret ()
 
 
 addToBuffer ::
@@ -316,13 +243,13 @@
 Same algorithm as in Synthesizer.Storable.Cut.arrangeEquidist
 -}
 makeArranger ::
-   (Storable.C a, Tuple.ValueOf a ~ value, A.Additive value) =>
+   (Storable.C a, MultiValue.Additive a) =>
    IO (SVL.ChunkSize ->
        EventList.T NonNeg.Int (SVL.Vector a) ->
        SVL.Vector a)
 makeArranger = do
-   mixer <- makeMixer A.add
-   fill <- fillBuffer A.zero
+   mixer <- makeMixer MultiValue.add
+   fill <- fillBuffer MultiValue.zero
    return $ \ (SVL.ChunkSize sz) ->
       let sznn = NonNeg.fromNumberMsg "arrange" sz
           go acc evs =
@@ -351,20 +278,3 @@
                    then []
                    else chunk : go newAcc future
       in  SVL.fromChunks . go []
-
-{- |
-This is unsafe since it relies on the prior initialization of the LLVM JIT.
-Better use 'makeArranger'.
--}
-{-# DEPRECATED arrange "better use makeArranger" #-}
-arrange ::
-   (Storable.C a, Tuple.ValueOf a ~ value, A.Additive value) =>
-      SVL.ChunkSize
-   -> EventList.T NonNeg.Int (SVL.Vector a)
-         {-^ A list of pairs: (relative start time, signal part),
-             The start time is relative to the start time
-             of the previous event. -}
-   -> SVL.Vector a
-         {-^ The mixed signal. -}
-arrange =
-   Unsafe.performIO makeArranger
diff --git a/src/Synthesizer/LLVM/Storable/Vector.hs b/src/Synthesizer/LLVM/Storable/Vector.hs
--- a/src/Synthesizer/LLVM/Storable/Vector.hs
+++ b/src/Synthesizer/LLVM/Storable/Vector.hs
@@ -1,18 +1,17 @@
 {-# LANGUAGE TypeFamilies #-}
 module Synthesizer.LLVM.Storable.Vector where
 
-import qualified LLVM.Extra.Storable as Storable
-
 import qualified Data.StorableVector as SV
 import qualified Data.StorableVector.Base as SVB
 
 import Foreign.Marshal.Array (advancePtr)
+import Foreign.Storable (Storable)
 import Foreign.ForeignPtr (ForeignPtr)
 import Foreign.Ptr (Ptr)
 import qualified System.Unsafe as Unsafe
 
 
-unsafeToPointers :: (Storable.C a) => SV.Vector a -> (ForeignPtr a, Ptr a, Int)
+unsafeToPointers :: (Storable a) => SV.Vector a -> (ForeignPtr a, Ptr a, Int)
 unsafeToPointers v =
    let (fp,s,l) = SVB.toForeignPtr v
    in  (fp, Unsafe.foreignPtrToPtr fp `advancePtr` s, l)
diff --git a/src/Synthesizer/LLVM/Value.hs b/src/Synthesizer/LLVM/Value.hs
new file mode 100644
--- /dev/null
+++ b/src/Synthesizer/LLVM/Value.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Synthesizer.LLVM.Value (
+   T, decons,
+   tau, square, sqrt,
+   max, min, limit, fraction,
+
+   (%==), (%/=), (%<), (%<=), (%>), (%>=), not,
+   (%&&), (%||),
+   (?), (??),
+
+   lift0, lift1, lift2, lift3,
+   unlift0, unlift1, unlift2, unlift3, unlift4, unlift5,
+   constantValue, constant,
+   fromInteger', fromRational',
+
+   Flatten(flattenCode, unfoldCode), Registers,
+   flatten, unfold,
+   flattenCodeTraversable, unfoldCodeTraversable,
+   flattenFunction,
+   ) where
+
+import LLVM.DSL.Value
+
+import qualified Synthesizer.LLVM.Frame.Stereo as Stereo ()
+import qualified Synthesizer.Basic.Phase as Phase
+
+import qualified Algebra.RealRing as RealRing
+
+import qualified Prelude as P ()
+import NumericPrelude.Base hiding (min, max, unzip, unzip3, not)
+
+
+instance (RealRing.C a, Flatten a) => Flatten (Phase.T a) where
+   type Registers (Phase.T a) = Registers a
+   flattenCode s = flattenCode $ Phase.toRepresentative s
+   unfoldCode s =
+      -- could also be unsafeFromRepresentative
+      Phase.fromRepresentative $ unfoldCode s
diff --git a/src/Synthesizer/LLVM/Wave.hs b/src/Synthesizer/LLVM/Wave.hs
--- a/src/Synthesizer/LLVM/Wave.hs
+++ b/src/Synthesizer/LLVM/Wave.hs
@@ -2,7 +2,7 @@
 {-# LANGUAGE TypeFamilies #-}
 module Synthesizer.LLVM.Wave where
 
-import qualified Synthesizer.LLVM.Simple.Value as Value
+import qualified Synthesizer.LLVM.Value as Value
 
 import qualified LLVM.Extra.Arithmetic as A
 
@@ -147,11 +147,24 @@
    A.sub (A.fromInteger' 1) <=<
    A.mul (A.fromInteger' 2)
 
+{- |
+> trapezoidSlope steepness = trapezoidSkew (recip steepness)
+-}
+trapezoidSlope ::
+   (A.PseudoRing a, A.RationalConstant a, A.Real a) =>
+   a -> a -> CodeGenFunction r a
+trapezoidSlope p =
+   A.max (A.fromInteger' (-1)) <=<
+   A.min (A.fromInteger' 1) <=<
+   A.mul p <=<
+   A.sub (A.fromInteger' 1) <=<
+   A.mul (A.fromInteger' 2)
+
 sine ::
    (A.Transcendental a, A.RationalConstant a) =>
    a -> CodeGenFunction r a
 sine t =
-   A.sin =<< A.mul t =<< Value.decons Value.twoPi
+   A.sin =<< A.mul t =<< Value.decons Value.tau
 
 
 
diff --git a/synthesizer-llvm.cabal b/synthesizer-llvm.cabal
--- a/synthesizer-llvm.cabal
+++ b/synthesizer-llvm.cabal
@@ -1,6 +1,6 @@
 Cabal-Version:  2.2
 Name:           synthesizer-llvm
-Version:        0.9
+Version:        1.0
 License:        GPL-3.0-only
 License-File:   LICENSE
 Author:         Henning Thielemann <haskell@henning-thielemann.de>
@@ -58,7 +58,7 @@
   default:     False
 
 Source-Repository this
-  Tag:         0.9
+  Tag:         1.0
   Type:        darcs
   Location:    http://code.haskell.org/synthesizer/llvm/
 
@@ -69,9 +69,9 @@
 
 Library
   Build-Depends:
-    llvm-dsl >=0.0 && <0.1,
-    llvm-extra >=0.10 && <0.11,
-    llvm-tf >=9.0 && <9.3,
+    llvm-dsl >=0.1 && <0.2,
+    llvm-extra >=0.11 && <0.12,
+    llvm-tf >=9.0 && <13.0,
     tfp >=1.0 && <1.1,
     vault >=0.3 && <0.4,
     synthesizer-core >=0.8 && <0.9,
@@ -86,9 +86,9 @@
     non-empty >=0.2.1 && <0.4,
     event-list >=0.1 && <0.2,
     pathtype >=0.8 && <0.9,
-    random >=1.0 && <1.2,
+    random >=1.0 && <1.3,
     containers >=0.1 && <0.7,
-    transformers >=0.2 && <0.6,
+    transformers >=0.2 && <0.7,
     semigroups >=0.1 && <1.0,
     utility-ht >=0.0.15 && <0.1
 
@@ -109,12 +109,11 @@
 
   Hs-source-dirs: src
   Exposed-Modules:
-    Synthesizer.LLVM.Simple.Signal
-    Synthesizer.LLVM.Simple.SignalPacked
-    Synthesizer.LLVM.Simple.Value
-    Synthesizer.LLVM.Parameterized.Signal
-    Synthesizer.LLVM.Parameterized.SignalPacked
-    Synthesizer.LLVM.Parameter
+    Synthesizer.LLVM.Generator.Signal
+    Synthesizer.LLVM.Generator.SignalPacked
+    Synthesizer.LLVM.Generator.Core
+    Synthesizer.LLVM.Generator.Source
+    Synthesizer.LLVM.Generator.Render
     Synthesizer.LLVM.Storable.Signal
     Synthesizer.LLVM.Storable.Process
     Synthesizer.LLVM.Causal.Process
@@ -122,16 +121,12 @@
     Synthesizer.LLVM.Causal.ProcessPacked
     Synthesizer.LLVM.Causal.Controlled
     Synthesizer.LLVM.Causal.ControlledPacked
-    Synthesizer.LLVM.CausalParameterized.Process
-    Synthesizer.LLVM.CausalParameterized.ProcessValue
-    Synthesizer.LLVM.CausalParameterized.ProcessPacked
-    Synthesizer.LLVM.CausalParameterized.Controlled
-    Synthesizer.LLVM.CausalParameterized.ControlledPacked
-    Synthesizer.LLVM.CausalParameterized.Functional
-    Synthesizer.LLVM.CausalParameterized.FunctionalPlug
-    Synthesizer.LLVM.CausalParameterized.RingBuffer
-    Synthesizer.LLVM.CausalParameterized.RingBufferForward
-    Synthesizer.LLVM.CausalParameterized.Helix
+    Synthesizer.LLVM.Causal.Exponential2
+    Synthesizer.LLVM.Causal.FunctionalPlug
+    Synthesizer.LLVM.Causal.Functional
+    Synthesizer.LLVM.Causal.RingBufferForward
+    Synthesizer.LLVM.Causal.Helix
+    Synthesizer.LLVM.Causal.Render
     Synthesizer.LLVM.Fold
     Synthesizer.LLVM.Plug.Input
     Synthesizer.LLVM.Plug.Output
@@ -147,13 +142,15 @@
     Synthesizer.LLVM.Filter.Moog
     Synthesizer.LLVM.Filter.Universal
     Synthesizer.LLVM.Filter.NonRecursive
-    Synthesizer.LLVM.Generator.Exponential2
     Synthesizer.LLVM.Interpolation
     Synthesizer.LLVM.Frame.SerialVector
-    Synthesizer.LLVM.Frame
-    Synthesizer.LLVM.Frame.Stereo
+    Synthesizer.LLVM.Frame.SerialVector.Class
+    Synthesizer.LLVM.Frame.SerialVector.Code
+    Synthesizer.LLVM.Frame.SerialVector.Plain
     Synthesizer.LLVM.Frame.StereoInterleaved
+    Synthesizer.LLVM.Frame.Stereo
     Synthesizer.LLVM.Frame.Binary
+    Synthesizer.LLVM.Frame
     Synthesizer.LLVM.Complex
     Synthesizer.LLVM.Wave
     Synthesizer.LLVM.MIDI
@@ -163,13 +160,14 @@
     Synthesizer.LLVM.Server.CausalPacked.Instrument
     Synthesizer.LLVM.Server.CausalPacked.InstrumentPlug
     Synthesizer.LLVM.Server.CausalPacked.Speech
+    Synthesizer.LLVM.Server.CausalPacked.Common
     Synthesizer.LLVM.Server.SampledSound
     Synthesizer.LLVM.Server.Common
     Synthesizer.LLVM.Server.CommonPacked
-    Synthesizer.LLVM.Server.Parameter
+    Synthesizer.LLVM.ConstantPiece
+    Synthesizer.LLVM.Value
 
   Other-Modules:
-    Synthesizer.LLVM.ConstantPiece
     Synthesizer.LLVM.ForeignPtr
     Synthesizer.LLVM.Random
     Synthesizer.LLVM.EventIterator
@@ -177,13 +175,12 @@
     Synthesizer.LLVM.Storable.ChunkIterator
     Synthesizer.LLVM.Storable.LazySizeIterator
     Synthesizer.LLVM.RingBuffer
-    Synthesizer.LLVM.Simple.SignalPrivate
-    Synthesizer.LLVM.Parameterized.SignalPrivate
-    Synthesizer.LLVM.Causal.ProcessPrivate
-    Synthesizer.LLVM.CausalParameterized.ProcessPrivate
-    -- experimental
-    Synthesizer.LLVM.Simple.Vanilla
-    -- Synthesizer.LLVM.Parameterized.Value
+    Synthesizer.LLVM.Causal.Parameterized
+    Synthesizer.LLVM.Causal.Private
+    Synthesizer.LLVM.Frame.StereoInterleavedCode
+    Synthesizer.LLVM.Generator.Extra
+    Synthesizer.LLVM.Generator.Private
+    Synthesizer.LLVM.Private
 
 Library server
   If flag(buildExamples)
@@ -199,7 +196,7 @@
       event-list,
       shell-utility >=0.0 && <0.2,
       pathtype,
-      optparse-applicative >=0.11 && <0.16,
+      optparse-applicative >=0.11 && <0.19,
       containers,
       utility-ht,
       base
@@ -225,6 +222,7 @@
       server,
       synthesizer-llvm,
 
+      llvm-dsl,
       llvm-extra,
       llvm-tf,
       tfp,
@@ -238,6 +236,7 @@
       non-empty,
       utility-ht,
       pathtype,
+      unsafe,
       base
   Else
     Buildable: False
@@ -256,12 +255,14 @@
   Main-Is:     Synthesizer/LLVM/Test.hs
   Other-Modules:
     Synthesizer.LLVM.LAC2011
+    Synthesizer.LLVM.ExampleUtility
 
 Executable synthi-llvm-lndw
   If flag(buildExamples) && flag(alsa)
     Build-Depends:
       synthesizer-llvm,
 
+      llvm-dsl,
       llvm-extra,
       llvm-tf,
       tfp,
@@ -300,6 +301,7 @@
   Main-Is:     Synthesizer/LLVM/TestALSA.hs
   Other-Modules:
     Synthesizer.LLVM.LNdW2011
+    Synthesizer.LLVM.ExampleUtility
 
 Executable synthi-llvm-alsa
   If flag(buildExamples) && flag(alsa)
@@ -307,6 +309,8 @@
       server,
       synthesizer-llvm,
 
+      unsafe,
+      llvm-dsl,
       llvm-tf,
       synthesizer-core,
       synthesizer-midi,
@@ -358,6 +362,7 @@
     Build-Depends:
       server,
       synthesizer-llvm,
+      tfp,
 
       jack >=0.7 && <0.8,
 
@@ -367,7 +372,7 @@
       storablevector,
       non-negative,
       random,
-      explicit-exception >=0.1.7 && <0.2,
+      explicit-exception >=0.1.7 && <0.3,
       event-list,
       pathtype,
       optparse-applicative,
@@ -458,6 +463,7 @@
       gnuplot >=0.5 && <0.6,
       pathtype,
       sox,
+      llvm-dsl,
       synthesizer-llvm,
       synthesizer-core,
       numeric-prelude,
@@ -481,8 +487,10 @@
 Test-Suite synthi-llvm-test
   Type: exitcode-stdio-1.0
   Build-Depends:
+    doctest-exitcode-stdio >=0.0 && <0.1,
     synthesizer-llvm,
 
+    llvm-dsl,
     llvm-extra,
     llvm-tf,
     tfp,
@@ -493,6 +501,7 @@
     utility-ht,
 
     QuickCheck >=1 && <3,
+    unsafe,
     base
   Default-Language: Haskell98
   GHC-Options:      -Wall
diff --git a/testsuite/Test/Main.hs b/testsuite/Test/Main.hs
--- a/testsuite/Test/Main.hs
+++ b/testsuite/Test/Main.hs
@@ -7,20 +7,26 @@
 
 import qualified LLVM.Core as LLVM
 
+import Control.Monad.IO.Class (liftIO)
+
 import Data.Tuple.HT (mapFst)
 
+import qualified Test.DocTest.Driver as DocTest
 
-prefix :: String -> [(String, IO ())] -> [(String, IO ())]
+
+prefix :: String -> [(String, prop)] -> [(String, prop)]
 prefix msg =
    map (mapFst (\str -> msg ++ "." ++ str))
 
 main :: IO ()
 main = do
    LLVM.initializeNativeTarget
-   mapM_ (\(name,test) -> putStr (name ++ ": ") >> test) $
-      concat $
-      prefix "Helix" Helix.tests :
-      prefix "RingBufferForward" RingBufferForward.tests :
-      prefix "Filter" Filter.tests :
-      prefix "Packed" Packed.tests :
+   DocTest.run $ mapM_
+      (\(name,prop) -> do
+         DocTest.printPrefix (name++": ")
+         DocTest.property =<< liftIO prop) $
+      prefix "Helix" Helix.tests ++
+      prefix "RingBufferForward" RingBufferForward.tests ++
+      prefix "Filter" Filter.tests ++
+      prefix "Packed" Packed.tests ++
       []
diff --git a/testsuite/Test/Synthesizer/LLVM/Filter.hs b/testsuite/Test/Synthesizer/LLVM/Filter.hs
--- a/testsuite/Test/Synthesizer/LLVM/Filter.hs
+++ b/testsuite/Test/Synthesizer/LLVM/Filter.hs
@@ -1,33 +1,33 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE Rank2Types #-}
 module Test.Synthesizer.LLVM.Filter (tests) where
 
+import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked
+                                                            as ComplexFilterP
+import qualified Synthesizer.LLVM.Filter.ComplexFirstOrder as ComplexFilter
 import qualified Synthesizer.LLVM.Filter.Allpass as Allpass
 import qualified Synthesizer.LLVM.Filter.FirstOrder as FirstOrder
 import qualified Synthesizer.LLVM.Filter.SecondOrder as SecondOrder
 import qualified Synthesizer.LLVM.Filter.SecondOrderPacked as SecondOrderP
-import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
 import qualified Synthesizer.LLVM.Filter.Moog as Moog
-import qualified Synthesizer.LLVM.Filter.ComplexFirstOrder as ComplexFilter
-import qualified Synthesizer.LLVM.Filter.ComplexFirstOrderPacked as ComplexFilterP
+import qualified Synthesizer.LLVM.Filter.Universal as UniFilter
 import qualified Synthesizer.LLVM.Filter.NonRecursive as FiltNR
 
 import qualified Synthesizer.Plain.Filter.Recursive.Allpass    as AllpassCore
 import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as FirstOrderCore
 import qualified Synthesizer.Plain.Filter.Recursive.Universal  as UniFilterCore
 import qualified Synthesizer.Plain.Filter.Recursive.Moog       as MoogCore
-import qualified Synthesizer.Plain.Filter.Recursive.FirstOrderComplex as ComplexFilterCore
+import qualified Synthesizer.Plain.Filter.Recursive.FirstOrderComplex
+                                                            as ComplexFilterCore
 
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Parameter as Param
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as Serial
 import qualified Synthesizer.LLVM.Wave as Wave
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Simple.Signal as Sig
-import Synthesizer.LLVM.CausalParameterized.Process (($<), ($*))
-import Synthesizer.LLVM.Parameter (($#))
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Core as Core
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import Synthesizer.LLVM.Causal.Process (($<), ($*))
 
 import Synthesizer.Plain.Filter.Recursive (Pole(Pole))
 import qualified Synthesizer.Interpolation.Module as Ip
@@ -52,16 +52,17 @@
     randomStorableVector, checkSimilarityPacked)
 
 import qualified Control.Category as Cat
-import Control.Category ((<<<))
-import Control.Arrow ((&&&), (^<<), (<<^))
+import Control.Category ((.), (<<<))
+import Control.Arrow ((&&&), (^<<))
 import Control.Applicative (liftA2, (<$>))
 
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Memory as Memory
 
-import qualified LLVM.Core as LLVM
-import LLVM.Core (Value)
-
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Data.Num.Decimal (D4)
 import Type.Base.Proxy (Proxy)
@@ -75,7 +76,7 @@
 import qualified Test.QuickCheck as QC
 
 import NumericPrelude.Numeric
-import NumericPrelude.Base
+import NumericPrelude.Base hiding ((.))
 
 
 type SimFloat = CheckSimilarity Float
@@ -96,63 +97,58 @@
 
 
 lfoSine ::
-   (Memory.C a) =>
-   (forall r. Value Float -> LLVM.CodeGenFunction r a) ->
-   Param.T p Float ->
-   SigP.T p a
+   (Memory.C a, Expr.Aggregate ae a) =>
+   (Exp Float -> ae) ->
+   Exp Float ->
+   Sig.T a
 lfoSine f reduct =
-   SigP.interpolateConstant reduct $
-   Sig.map f $
-   CausalP.apply (CausalP.mapExponential 2 0.01) $
-   SigP.osciSimple Wave.sine 0 (fmap (* (0.1/44100)) reduct)
+   Sig.interpolateConstant reduct $
+   (Causal.map f . Causal.mapExponential 2 0.01 $*
+      Sig.osci Wave.sine 0 (reduct * (0.1/44100)))
 
 allpassControl ::
    (TypeNum.Natural n) =>
    Proxy n ->
-   Param.T p Float ->
-   SigP.T p (Allpass.CascadeParameter n (Value Float))
+   Exp Float ->
+   Sig.T (Allpass.CascadeParameter n (MultiValue.T Float))
 allpassControl order =
    lfoSine (Allpass.flangerParameter order)
 
 allpassPhaserCausal, allpassPhaserPipeline ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Value Float)
-allpassPhaserCausal reduct =
-   CausalP.apply
-      (Allpass.phaser
-       $< allpassControl TypeNum.d16 reduct)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (MultiValue.T Float)
+allpassPhaserCausal reduct xs =
+   Allpass.phaser
+      $< allpassControl TypeNum.d16 reduct
+      $* xs
 
 allpassPhaserPipeline reduct xs =
    let order = TypeNum.d16
-   in  (SigP.drop $# TypeNum.integralFromProxy order) $
+   in  (Sig.drop (TypeNum.integralFromProxy order)) $
        (Allpass.phaserPipeline
          $< allpassControl order reduct
          $* xs)
 
 
-genOsci :: Gen.T (Param.T p) (Float, Float) (Param.T p Float, Param.T p Float)
+genOsci :: QC.Gen (Float, Float)
 genOsci = pair (Gen.choose (0.001, 0.01)) (Gen.choose (0, 0.99))
 
-genOsciReduct ::
-   Gen.T
-      (Param.T p) ((Float, Float), Float)
-      ((Param.T p Float, Param.T p Float), Param.T p Float)
+genOsciReduct :: QC.Gen ((Float, Float), Float)
 genOsciReduct = pair genOsci (Gen.choose (10, 100))
 
-genOsciReductPacked ::
-   Gen.T
-      (Param.T p) ((Float, Float), Float)
-      ((Param.T p Float, Param.T p Float), Param.T p Float)
+genOsciReductPacked :: QC.Gen ((Float, Float), Float)
 genOsciReductPacked = pair genOsci (arg $ (4*) <$> QC.choose (1, 25))
 
 allpassPipeline :: Gen.Test ((Float,Float), Float) SimFloat
 allpassPipeline =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
-   let tone = SigP.osciSimple Wave.triangle phase freq
-   in  checkSimilarity 1e-2 limitFloat
-          (allpassPhaserCausal reduct tone)
-          (allpassPhaserPipeline reduct tone)
+   withGenArgs genOsciReduct $
+   let tone (freq,phase) = Sig.osci Wave.triangle phase freq
+   in checkSimilarity 1e-2 limitFloat
+         (\(freqPhase, reduct) ->
+            allpassPhaserCausal reduct $ tone freqPhase)
+         (\(freqPhase, reduct) ->
+            allpassPhaserPipeline reduct $ tone freqPhase)
 
 
 
@@ -162,33 +158,33 @@
 -}
 applyPacked ::
    (Memory.C c) =>
-   CausalP.T p (c, VectorValue) VectorValue ->
-   SigP.T p c ->
-   SigP.T p VectorValue ->
-   SigP.T p VectorValue
+   Causal.T (c, VectorValue) VectorValue ->
+   Sig.T c ->
+   Sig.T VectorValue ->
+   Sig.T VectorValue
 applyPacked proc cs xs =
    proc
-      $< ((SigP.interpolateConstant $#
-            (recip $ TypeNum.integralFromProxy TypeNum.d4 :: Float)) cs)
+      $< Sig.interpolateConstant
+            (recip $ TypeNum.integralFromProxy TypeNum.d4 :: Exp Float) cs
       $* xs
 
 
 allpassPhaserPacked ::
-   Param.T p Float ->
-   SigP.T p VectorValue ->
-   SigP.T p VectorValue
+   Exp Float ->
+   Sig.T VectorValue ->
+   Sig.T VectorValue
 allpassPhaserPacked reduct =
    applyPacked Allpass.phaserPacked
       (allpassControl TypeNum.d16 reduct)
 
 allpassPacked :: Gen.Test ((Float,Float), Float) SimFloat
 allpassPacked =
-   withGenArgs genOsciReductPacked $ \((freq,phase), reduct) ->
-   let tone  = SigP.osciSimple  Wave.triangle phase freq
-       toneP = SigPS.osciSimple Wave.triangle phase freq
+   withGenArgs genOsciReductPacked $
+   let tone  (freq,phase) = Sig.osci  Wave.triangle phase freq
+       toneP (freq,phase) = SigPS.osci Wave.triangle phase freq
    in  checkSimilarityPacked 1e-2 limitFloat
-          (allpassPhaserCausal reduct tone)
-          (allpassPhaserPacked reduct toneP)
+          (\(freqPhase, reduct) -> allpassPhaserCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) -> allpassPhaserPacked reduct $ toneP freqPhase)
 
 
 interpolateConstant :: Float -> SigS.T a -> SigS.T a
@@ -225,44 +221,43 @@
 
 allpassCore :: Gen.Test ((Float,Float), Float) SimStateFloat
 allpassCore =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
-   let tone = SigP.osciSimple Wave.triangle phase freq
-       toneS p =
+   withGenArgs genOsciReduct $
+   let tone (freq,phase) = Sig.osci Wave.triangle phase freq
+       toneS (freq,phase) =
           OsciS.static WaveCore.triangle
-             (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)
+             (Phase.fromRepresentative phase) freq
    in  checkSimilarityState 1e-2 limitFloat
-          (allpassPhaserCausal reduct tone)
-          (\p -> allpassPhaserCore (Param.get reduct p) (toneS p))
+          (\(freqPhase, reduct) -> allpassPhaserCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) -> allpassPhaserCore reduct $ toneS freqPhase)
 
 
 
-diracImpulse :: SigP.T p (Value Float)
-diracImpulse =
-   (CausalP.delay1 $# (one::Float)) $*
-   (SigP.constant $# (zero::Float))
+diracImpulse :: Sig.T (MultiValue.T Float)
+diracImpulse = Causal.delay1 one $* Sig.constant zero
 
 firstOrderConstant ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Value Float)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (MultiValue.T Float)
 firstOrderConstant cutOff xs =
    FirstOrder.lowpassCausal
-    $< SigP.constant (FirstOrderCore.parameter ^<< cutOff)
+    $< Sig.constant (FirstOrderCore.parameter cutOff)
     $* xs
 
 firstOrderExponential :: Gen.Test Float SimFloat
 firstOrderExponential =
-   withGenArgs (Gen.choose (0.001, 0.01)) $ \cutOff ->
-   let gain = exp(-2*pi*cutOff)
+   withGenArgs (Gen.choose (0.001, 0.01)) $
+   let gain cutOff = exp(-2*pi*cutOff)
    in  checkSimilarity 1e-2 limitFloat
-          (SigP.amplify (recip (1 - gain)) $
-           firstOrderConstant cutOff diracImpulse)
-          (SigP.exponentialCore gain $# (one :: Float))
+          (\cutOff ->
+             Causal.amplify (recip (1 - gain cutOff)) $*
+             firstOrderConstant cutOff diracImpulse)
+          (\cutOff -> Core.exponential (gain cutOff) one)
 
 firstOrderCausal ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Value Float)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (MultiValue.T Float)
 firstOrderCausal reduct xs =
    FirstOrder.lowpassCausal
     $< lfoSine FirstOrder.parameter reduct
@@ -280,19 +275,19 @@
 
 firstOrder :: Gen.Test ((Float,Float), Float) SimStateFloat
 firstOrder =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
-   let tone = SigP.osciSimple Wave.triangle phase freq
-       toneS p =
+   withGenArgs genOsciReduct $
+   let tone (freq,phase) = Sig.osci Wave.triangle phase freq
+       toneS (freq,phase) =
           OsciS.static WaveCore.triangle
-             (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)
+             (Phase.fromRepresentative phase) freq
    in  checkSimilarityState 1e-2 limitFloat
-          (firstOrderCausal reduct tone)
-          (\p -> firstOrderCore (Param.get reduct p) (toneS p))
+          (\(freqPhase, reduct) -> firstOrderCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) -> firstOrderCore reduct $ toneS freqPhase)
 
 firstOrderCausalPacked ::
-   Param.T p Float ->
-   SigP.T p VectorValue ->
-   SigP.T p VectorValue
+   Exp Float ->
+   Sig.T VectorValue ->
+   Sig.T VectorValue
 firstOrderCausalPacked reduct =
    applyPacked
       FirstOrder.lowpassCausalPacked
@@ -300,56 +295,62 @@
 
 firstOrderPacked :: Gen.Test ((Float,Float), Float) SimFloat
 firstOrderPacked =
-   withGenArgs genOsciReductPacked $ \((freq,phase), reduct) ->
-   let tone  = SigP.osciSimple  Wave.triangle phase freq
-       toneP = SigPS.osciSimple Wave.triangle phase freq
+   withGenArgs genOsciReductPacked $
+   let tone  (freq,phase) = Sig.osci  Wave.triangle phase freq
+       toneP (freq,phase) = SigPS.osci Wave.triangle phase freq
    in  checkSimilarityPacked 1e-2 limitFloat
-          (firstOrderCausal reduct tone)
-          (firstOrderCausalPacked reduct toneP)
+          (\(freqPhase, reduct) ->
+             firstOrderCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) ->
+             firstOrderCausalPacked reduct $ toneP freqPhase)
 
 
 secondOrderCausal ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Value Float)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (MultiValue.T Float)
 secondOrderCausal reduct xs =
    SecondOrder.causal
-    $< lfoSine (SecondOrder.bandpassParameter (LLVM.valueOf (10::Float))) reduct
+    $< lfoSine (SecondOrder.bandpassParameter 10) reduct
     $* xs
 
 secondOrderCausalPacked ::
-   Param.T p Float ->
-   SigP.T p VectorValue ->
-   SigP.T p VectorValue
+   Exp Float ->
+   Sig.T VectorValue ->
+   Sig.T VectorValue
 secondOrderCausalPacked reduct =
    applyPacked SecondOrder.causalPacked
-      (lfoSine (SecondOrder.bandpassParameter (LLVM.valueOf (10::Float))) reduct)
+      (lfoSine (SecondOrder.bandpassParameter 10) reduct)
 
 secondOrderPacked :: Gen.Test ((Float,Float), Float) SimFloat
 secondOrderPacked =
-   withGenArgs genOsciReductPacked $ \((freq,phase), reduct) ->
-   let tone  = SigP.osciSimple  Wave.triangle phase freq
-       toneP = SigPS.osciSimple Wave.triangle phase freq
+   withGenArgs genOsciReductPacked $
+   let tone  (freq,phase) = Sig.osci  Wave.triangle phase freq
+       toneP (freq,phase) = SigPS.osci Wave.triangle phase freq
    in  checkSimilarityPacked 1e-2 limitFloat
-          (secondOrderCausal reduct tone)
-          (secondOrderCausalPacked reduct toneP)
+          (\(freqPhase, reduct) ->
+             secondOrderCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) ->
+             secondOrderCausalPacked reduct $ toneP freqPhase)
 
 secondOrderCausalPacked2 ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Value Float)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (MultiValue.T Float)
 secondOrderCausalPacked2 reduct xs =
    SecondOrderP.causal
-    $< lfoSine (SecondOrderP.bandpassParameter (LLVM.valueOf (10::Float))) reduct
+    $< lfoSine (SecondOrderP.bandpassParameter 10) reduct
     $* xs
 
 secondOrderPacked2 :: Gen.Test ((Float,Float), Float) SimFloat
 secondOrderPacked2 =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
-   let tone = SigP.osciSimple  Wave.triangle phase freq
+   withGenArgs genOsciReduct $
+   let tone (freq,phase) = Sig.osci  Wave.triangle phase freq
    in  checkSimilarity 1e-2 limitFloat
-          (secondOrderCausal reduct tone)
-          (secondOrderCausalPacked2 reduct tone)
+          (\(freqPhase, reduct) ->
+             secondOrderCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) ->
+             secondOrderCausalPacked2 reduct $ tone freqPhase)
 
 
 {-
@@ -360,12 +361,12 @@
 -}
 
 universalCausal ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (UniFilter.Result (Value Float))
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (UniFilter.Result (MultiValue.T Float))
 universalCausal reduct xs =
    UniFilter.causal
-    $< lfoSine (UniFilter.parameter (LLVM.valueOf (10::Float))) reduct
+    $< lfoSine (UniFilter.parameter 10) reduct
     $* xs
 
 {-# INLINE universalCore #-}
@@ -380,17 +381,18 @@
 
 universal :: Gen.Test ((Float,Float), Float) SimStateFloat
 universal =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
-   let tone = SigP.osciSimple Wave.triangle phase freq
-       toneS p =
+   withGenArgs genOsciReduct $
+   let tone (freq,phase) = Sig.osci Wave.triangle phase freq
+       toneS (freq,phase) =
           OsciS.static WaveCore.triangle
-             (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)
+             (Phase.fromRepresentative phase) freq
    in  checkSimilarityState 1e-2 limitFloat
-          (fmap UniFilter.lowpass $
-             universalCausal reduct tone)
-          (\p ->
+          (\(freqPhase, reduct) ->
+             fmap UniFilter.lowpass $
+             universalCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) ->
              SigS.map UniFilterCore.lowpass $
-             universalCore (Param.get reduct p) (toneS p))
+             universalCore reduct $ toneS freqPhase)
 {-
        checkSimilarityState 1e-2 limitUniFilter
           (universalCausal reduct tone)
@@ -401,12 +403,12 @@
 moogCausal ::
    (TypeNum.Natural n) =>
    Proxy n ->
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Value Float)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (MultiValue.T Float)
 moogCausal order reduct xs =
    Moog.causal
-    $< lfoSine (Moog.parameter order (LLVM.valueOf (10::Float))) reduct
+    $< lfoSine (Moog.parameter order 10) reduct
     $* xs
 
 {-# INLINE moogCore #-}
@@ -422,46 +424,49 @@
 
 moog :: Gen.Test ((Float,Float), Float) SimStateFloat
 moog =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
+   withGenArgs genOsciReduct $
    let order = TypeNum.d6
-       tone  = SigP.osciSimple Wave.triangle phase freq
-       toneS p =
+       tone  (freq,phase) = Sig.osci Wave.triangle phase freq
+       toneS (freq,phase) =
           OsciS.static WaveCore.triangle
-             (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)
+             (Phase.fromRepresentative phase) freq
    in  checkSimilarityState 1e-2 limitFloat
-          (moogCausal order reduct tone)
-          (\p -> moogCore (TypeNum.integralFromProxy order) (Param.get reduct p) (toneS p))
+         (\(freqPhase, reduct) ->
+            moogCausal order reduct $ tone freqPhase)
+         (\(freqPhase, reduct) ->
+            moogCore (TypeNum.integralFromProxy order) reduct $
+            toneS freqPhase)
 
 
 complexCausal ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Stereo.T (Value Float))
-complexCausal reduct =
-   CausalP.apply $
-      (ComplexFilter.causal
-        $< lfoSine (ComplexFilter.parameter (LLVM.valueOf (10::Float))) reduct)
-      <<^ (\x -> Stereo.cons x A.zero)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (Stereo.T (MultiValue.T Float))
+complexCausal reduct xs =
+   ComplexFilter.causal
+      $< lfoSine (ComplexFilter.parameter 10) reduct
+      $* ((\x -> Stereo.cons x A.zero) <$> xs)
 
 complexCausalPacked ::
-   Param.T p Float ->
-   SigP.T p (Value Float) ->
-   SigP.T p (Stereo.T (Value Float))
-complexCausalPacked reduct =
-   CausalP.apply $
-      (ComplexFilterP.causal
-        $< lfoSine (ComplexFilterP.parameter (LLVM.valueOf (10::Float))) reduct)
-      <<^ (\x -> Stereo.cons x A.zero)
+   Exp Float ->
+   Sig.T (MultiValue.T Float) ->
+   Sig.T (Stereo.T (MultiValue.T Float))
+complexCausalPacked reduct xs =
+   ComplexFilterP.causal
+      $< lfoSine (ComplexFilterP.parameter 10) reduct
+      $* ((\x -> Stereo.cons x A.zero) <$> xs)
 
 complexPacked :: Gen.Test ((Float,Float), Float) SimFloat
 complexPacked =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
-   let tone = SigP.osciSimple Wave.triangle phase freq
+   withGenArgs genOsciReduct $
+   let tone (freq,phase) = Sig.osci Wave.triangle phase freq
    in  checkSimilarity 1e-2 limitFloat
-          (fmap Stereo.left $
-             complexCausal reduct tone)
-          (fmap Stereo.left $
-             complexCausalPacked reduct tone)
+          (\(freqPhase, reduct) ->
+             fmap Stereo.left $
+             complexCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) ->
+             fmap Stereo.left $
+             complexCausalPacked reduct $ tone freqPhase)
 
 {-# INLINE complexCore #-}
 complexCore ::
@@ -476,17 +481,18 @@
 
 complex :: Gen.Test ((Float,Float), Float) SimStateFloat
 complex =
-   withGenArgs genOsciReduct $ \((freq,phase), reduct) ->
-   let tone = SigP.osciSimple Wave.triangle phase freq
-       toneS p =
+   withGenArgs genOsciReduct $
+   let tone (freq,phase) = Sig.osci Wave.triangle phase freq
+       toneS (freq,phase) =
           OsciS.static WaveCore.triangle
-             (Phase.fromRepresentative (Param.get phase p)) (Param.get freq p)
+             (Phase.fromRepresentative phase) freq
    in  checkSimilarityState 1e-2 limitFloat
-          (fmap Stereo.left $
-             complexCausal reduct tone)
-          (\p ->
+          (\(freqPhase, reduct) ->
+             fmap Stereo.left $
+             complexCausal reduct $ tone freqPhase)
+          (\(freqPhase, reduct) ->
              SigS.map ((0.1*) . Stereo.left) $
-             complexCore (Param.get reduct p) (toneS p))
+             complexCore reduct $ toneS freqPhase)
 {-
    in  checkSimilarityState 1e-2 limitStereoFloat
           (complexCausal reduct tone)
@@ -501,16 +507,17 @@
          (arg $ liftA2 (,) (QC.choose (1,20)) (Rnd.mkStdGen <$> QC.arbitrary))
          Gen.arbitrary)
    $
-   \(rnd, seed) ->
-   let mask = randomStorableVector (-1,1::Float) <$> rnd
-       noise  = SigP.noise seed 1
-       noiseP = SigPS.noise seed 1
-   in  checkSimilarityPacked 1e-3 limitFloat
-          (FiltNR.convolve mask $* noise)
-          (FiltNR.convolvePacked mask $* noiseP)
+   fmap
+      (\f chunkSize (rnd, seed) ->
+         f chunkSize
+            (Render.buffer $ randomStorableVector (-1,1::Float) rnd, seed))
+   $
+   checkSimilarityPacked 1e-3 limitFloat
+      (\(mask, seed) -> FiltNR.convolve mask $* Sig.noise seed 1)
+      (\(mask, seed) -> FiltNR.convolvePacked mask $* SigPS.noise seed 1)
 
 
-tests :: [(String, IO ())]
+tests :: [(String, IO QC.Property)]
 tests =
    ("secondOrderPacked", checkWithParam secondOrderPacked) :
    ("secondOrderPacked2", checkWithParam secondOrderPacked2) :
diff --git a/testsuite/Test/Synthesizer/LLVM/Generator.hs b/testsuite/Test/Synthesizer/LLVM/Generator.hs
--- a/testsuite/Test/Synthesizer/LLVM/Generator.hs
+++ b/testsuite/Test/Synthesizer/LLVM/Generator.hs
@@ -1,7 +1,5 @@
 module Test.Synthesizer.LLVM.Generator where
 
-import qualified Synthesizer.LLVM.Parameter as Param
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as F
 
 import Data.StorableVector.Lazy (ChunkSize)
 
@@ -15,50 +13,33 @@
 import Prelude hiding (id)
 
 
-data T f p a = Cons (QC.Gen p) (F.PrepareArguments f p a)
+type T f p a = QC.Gen p
 
-arg :: QC.Gen a -> T f a (f a)
-arg gen = Cons gen F.atomArg
+type Param p = (->) p
 
-arbitrary :: (QC.Arbitrary a) => T f a (f a)
-arbitrary = arg QC.arbitrary
+arg :: QC.Gen a -> QC.Gen a
+arg = id
 
-choose :: (Random a) => (a,a) -> T f a (f a)
-choose rng = arg $ QC.choose rng
+arbitrary :: (QC.Arbitrary a) => QC.Gen a
+arbitrary = QC.arbitrary
 
+choose :: (Random a) => (a,a) -> QC.Gen a
+choose = QC.choose
 
-pair ::
-   (Functor f) =>
-   T f a0 b0 ->
-   T f a1 b1 ->
-   T f (a0,a1) (b0,b1)
-pair (Cons g0 p0) (Cons g1 p1) =
-   Cons (liftA2 (,) g0 g1) (F.pairArgs p0 p1)
 
-triple ::
-   (Functor f) =>
-   T f a0 b0 ->
-   T f a1 b1 ->
-   T f a2 b2 ->
-   T f (a0,a1,a2) (b0,b1,b2)
-triple (Cons g0 p0) (Cons g1 p1) (Cons g2 p2) =
-   Cons (liftA3 (,,) g0 g1 g2) (F.tripleArgs p0 p1 p2)
-
-withGenArgs ::
-   T (Param.T p) p a ->
-   (a -> IO (ChunkSize -> p -> test)) -> Test p test
-withGenArgs (Cons gen prepArgs) f =
-   (gen, withPreparedArgs prepArgs f)
+pair :: QC.Gen a -> QC.Gen b -> QC.Gen (a,b)
+pair = liftA2 (,)
 
+triple :: QC.Gen a -> QC.Gen b -> QC.Gen c -> QC.Gen (a,b,c)
+triple = liftA3 (,,)
 
-withPreparedArgs ::
-   F.PrepareArguments (Param.T p) p a -> (a -> test) -> test
-withPreparedArgs (F.PrepareArguments prepare) f = f $ prepare id
+withGenArgs :: QC.Gen p -> (IO (ChunkSize -> p -> test)) -> Test p test
+withGenArgs = (,)
 
 
 type Test p test = (QC.Gen p, IO (ChunkSize -> p -> test))
 
-checkWithParam :: (Show p, QC.Testable test) => Test p test -> IO ()
+checkWithParam :: (Show p, QC.Testable test) => Test p test -> IO QC.Property
 checkWithParam (gen, test) = do
    f <- test
-   QC.quickCheck (QC.forAll gen $ flip f)
+   return $ QC.property (QC.forAll gen $ flip f)
diff --git a/testsuite/Test/Synthesizer/LLVM/Helix.hs b/testsuite/Test/Synthesizer/LLVM/Helix.hs
--- a/testsuite/Test/Synthesizer/LLVM/Helix.hs
+++ b/testsuite/Test/Synthesizer/LLVM/Helix.hs
@@ -1,41 +1,42 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE Rank2Types #-}
 module Test.Synthesizer.LLVM.Helix (tests) where
 
-import qualified Synthesizer.LLVM.CausalParameterized.Helix as Helix
-import qualified Synthesizer.LLVM.CausalParameterized.Functional as Func
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Parameter as Param
+import qualified Synthesizer.LLVM.Causal.Helix as Helix
+import qualified Synthesizer.LLVM.Causal.Functional as Func
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.Source as Source
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
 import qualified Synthesizer.LLVM.Interpolation as Interpolation
-import Synthesizer.LLVM.CausalParameterized.Functional (($&), (&|&))
-import Synthesizer.LLVM.CausalParameterized.Process (($*))
-import Synthesizer.LLVM.Parameter (($#))
+import Synthesizer.LLVM.Causal.Functional (($&), (&|&))
+import Synthesizer.LLVM.Causal.Process (($*))
 
 import qualified Data.StorableVector.Lazy as SVL
-import qualified Data.StorableVector as SV
 import Data.StorableVector.Lazy (ChunkSize)
 
-import Test.Synthesizer.LLVM.Generator (withPreparedArgs, checkWithParam)
+import Test.Synthesizer.LLVM.Generator (checkWithParam)
 import Test.Synthesizer.LLVM.Utility
           (CheckSimilarity, checkSimilarity,
-           genRandomVectorParam, randomSignal)
+           genRandomVectorParam, randomStorableVectorLoop)
 
-import Control.Arrow (arr)
-import Control.Applicative (pure, liftA2)
+import qualified LLVM.DSL.Expression as Expr
+import LLVM.DSL.Expression (Exp)
 
-import LLVM.Core (Value)
+import qualified LLVM.Extra.Multi.Value as MultiValue
 
 import Foreign.Storable (Storable)
 
 import qualified System.Random as Rnd
 import Data.Word (Word32)
 
+import Control.Applicative (liftA2)
+
 -- import qualified Graphics.Gnuplot.Simple as Gnuplot
 import qualified Test.QuickCheck as QC
 
+import qualified Algebra.Ring as Ring
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -50,11 +51,11 @@
 limitFloat = SVL.take signalLength
 
 
-randomSpeed :: Param.T p (Int, Rnd.StdGen) -> SigP.T p (Value Float)
-randomSpeed = randomSignal (0,10::Float)
+randomSpeed :: (Int, Rnd.StdGen) -> SVL.Vector Float
+randomSpeed = randomStorableVectorLoop (0,10)
 
-randomPhase :: Param.T p (Int, Rnd.StdGen) -> SigP.T p (Value Float)
-randomPhase = randomSignal (0,1::Float)
+randomPhase :: (Int, Rnd.StdGen) -> SVL.Vector Float
+randomPhase = randomStorableVectorLoop (0,1)
 
 genStaticDynamic ::
    QC.Gen (((Int, Rnd.StdGen), (Int, Rnd.StdGen)), (Float, Word32))
@@ -67,36 +68,44 @@
    IO (ChunkSize ->
        (((Int, Rnd.StdGen), (Int, Rnd.StdGen)), (Float, Word32)) -> SimFloat)
 staticDynamic =
-   withPreparedArgs
-      (Func.pairArgs
-         (Func.pairArgs Func.atomArg Func.atomArg)
-         (Func.pairArgs Func.atomArg Func.atomArg)) $
-      \((speedParam, phaseParam), (period, noiseParam)) ->
-   let len = 1000
-       noise :: Param.T p Word32 -> SigP.T p (Value Float)
-       noise seed = CausalP.take (pure len) $* SigP.noise seed 1
+   let len :: (Ring.C a) => a
+       len = 1000
+       noise :: Exp Word32 -> Sig.T (MultiValue.T Float)
+       noise seed = Sig.noise seed 1
 
-       static =
+       static, dynamic ::
+          ((Sig.T (MultiValue.T Float), Sig.T (MultiValue.T Float)),
+           Exp Float,
+           (Exp Word32, Exp (Source.StorableVector Float))) ->
+          Func.T inp (MultiValue.T Float)
+       static ((speedSig, phaseSig), period, (_, noiseSig)) =
           Helix.static Interpolation.linear Interpolation.linear
-             (fmap round period) period
-             (fmap (\seed -> SigP.render (noise (arr id)) len seed :: SV.Vector Float) noiseParam)
+             (Expr.roundToIntFast period) period noiseSig
           $&
-          Func.fromSignal
-             ((CausalP.integrate $# (0::Float)) $* randomSpeed speedParam)
+          Func.fromSignal (Causal.integrate zero $* speedSig)
           &|&
-          Func.fromSignal (randomPhase phaseParam)
+          Func.fromSignal phaseSig
 
-       dynamic =
+       dynamic ((speedSig, phaseSig), period, (noiseParam, _)) =
           Helix.dynamic Interpolation.linear Interpolation.linear
-             (fmap round period) period (noise noiseParam)
+             (Expr.roundToIntFast period) period
+             (Causal.take len $* noise noiseParam)
           $&
-          Func.fromSignal (randomSpeed speedParam)
+          Func.fromSignal speedSig
           &|&
-          Func.fromSignal (randomPhase phaseParam)
+          Func.fromSignal phaseSig
 
-   in  checkSimilarity 5e-3 limitFloat
-          (Func.compileSignal static)
-          (Func.compileSignal dynamic)
+   in liftA2
+         (\noiseSig f chunkSize
+               ((speedParam, phaseParam), (period, noiseParam)) ->
+            f chunkSize
+               ((randomSpeed speedParam, randomPhase phaseParam),
+                period,
+                (noiseParam, Render.buffer (noiseSig len noiseParam))))
+         (Render.run noise)
+         (checkSimilarity 5e-3 limitFloat
+            (Func.compileSignal . static)
+            (Func.compileSignal . dynamic))
 
 {-
 plot :: IO ()
@@ -111,7 +120,7 @@
 -}
 
 
-tests :: [(String, IO ())]
+tests :: [(String, IO QC.Property)]
 tests =
    ("staticDynamic", checkWithParam (genStaticDynamic, staticDynamic)) :
    []
diff --git a/testsuite/Test/Synthesizer/LLVM/Packed.hs b/testsuite/Test/Synthesizer/LLVM/Packed.hs
--- a/testsuite/Test/Synthesizer/LLVM/Packed.hs
+++ b/testsuite/Test/Synthesizer/LLVM/Packed.hs
@@ -9,36 +9,39 @@
     CheckSimilarity, CheckEquality, checkSimilarityPacked)
 
 import qualified Synthesizer.LLVM.Wave as Wave
-import qualified Synthesizer.LLVM.Parameter as Param
+import LLVM.DSL.Expression (Exp)
 
 import Type.Data.Num.Decimal (D4)
 import qualified Type.Data.Num.Decimal as TypeNum
 
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
-import qualified Synthesizer.LLVM.Generator.Exponential2 as Exp
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import Synthesizer.LLVM.CausalParameterized.Process (($*))
+import qualified Synthesizer.LLVM.Frame.SerialVector.Plain as SerialPlain
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as SerialCode
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Core as SigCore
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Causal.Exponential2 as Exp
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import Synthesizer.LLVM.Causal.Process (($*))
 
 import qualified Synthesizer.LLVM.Storable.Signal as SigStL
 import qualified Data.StorableVector.Lazy as SVL
 import Data.StorableVector.Lazy (ChunkSize)
 
-import Control.Arrow (arr, (<<<))
+import Control.Arrow ((<<<))
 import Control.Applicative ((<$>))
 
-import Data.Word (Word32)
+import Data.Word (Word, Word32)
 
 import qualified Test.QuickCheck as QC
-import Test.QuickCheck (quickCheck)
 
+import qualified Algebra.Ring as Ring
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
 
 type SimFloat = CheckSimilarity Float
-type VectorValue = Serial.Value D4 Float
+type VectorValue = SerialCode.Value D4 Float
 
 signalLength :: Int
 signalLength = 10000
@@ -48,87 +51,87 @@
 limitFloat = SVL.take signalLength
 
 
-withDur ::
-   (Param.T Float Float -> IO (ChunkSize -> Float -> test)) ->
-   Test Float test
+withDur :: (Ring.C a) => IO (ChunkSize -> a -> b) -> Test a b
 withDur =
    withGenArgs (arg (fromIntegral <$> QC.choose (signalLength, 2*signalLength)))
 
 {-
 limitPackedFloat ::
-   SVL.Vector (Serial.Plain D4 Float) -> SVL.Vector (Serial.Plain D4 Float)
+   SVL.Vector (SerialPlain.T D4 Float) -> SVL.Vector (SerialPlain.T D4 Float)
 limitPackedFloat = SVL.take (div signalLength 4)
 -}
 
 constant :: Test Float SimFloat
 constant =
-   withGenArgs (Gen.choose (-1, 1)) $ \y ->
+   withGenArgs (Gen.choose (-1, 1)) $
       checkSimilarityPacked 1e-3 limitFloat
-         (SigP.constant y) (SigPS.constant y)
+         (\y -> Sig.constant y) (\y -> SigPS.constant y)
 
 ramp :: Test Float SimFloat
 ramp =
-   withDur $ \dur ->
+   withDur $
       checkSimilarityPacked 1e-3 limitFloat
-         (SigP.rampInf dur) (SigPS.rampInf dur)
+         (\dur -> Sig.rampInf dur) (\dur -> SigPS.rampInf dur)
 
 parabolaFadeIn :: Test Float SimFloat
 parabolaFadeIn =
-   withDur $ \dur ->
+   withDur $
       checkSimilarityPacked 1e-3 limitFloat
-         (SigP.parabolaFadeInInf dur)
-         (SigPS.parabolaFadeInInf dur)
+         (\dur -> Sig.parabolaFadeInInf dur)
+         (\dur -> SigPS.parabolaFadeInInf dur)
 
 parabolaFadeOut :: Test Float SimFloat
 parabolaFadeOut =
-   withDur $ \dur ->
+   withDur $
       checkSimilarityPacked 1e-3 limitFloat
-         (SigP.parabolaFadeOutInf dur)
-         (SigPS.parabolaFadeOutInf dur)
+         (\dur -> Sig.parabolaFadeOutInf dur)
+         (\dur -> SigPS.parabolaFadeOutInf dur)
 
-parabolaFadeInMap :: Test Float SimFloat
+parabolaFadeInMap :: Test Word SimFloat
 parabolaFadeInMap =
-   withDur $ \dur ->
+   withDur $
       checkSimilarity 1e-3 limitFloat
-          (SigP.parabolaFadeIn dur)
-          (SigP.parabolaFadeInMap dur)
+          (\dur -> Sig.parabolaFadeIn dur)
+          (\dur -> Sig.parabolaFadeInMap dur)
 
-parabolaFadeOutMap :: Test Float SimFloat
+parabolaFadeOutMap :: Test Word SimFloat
 parabolaFadeOutMap =
-   withDur $ \dur ->
+   withDur $
       checkSimilarity 1e-3 limitFloat
-          (SigP.parabolaFadeOut dur)
-          (SigP.parabolaFadeOutMap dur)
+          (\dur -> Sig.parabolaFadeOut dur)
+          (\dur -> Sig.parabolaFadeOutMap dur)
 
 
-genExp :: Gen.T (Param.T p) (Float, Float) (Param.T p Float, Param.T p Float)
+genExp :: QC.Gen (Float, Float)
 genExp = pair (Gen.choose (1000,10000)) (Gen.choose (-1,1))
 
 exponential2 :: Test (Float,Float) SimFloat
 exponential2 =
-   withGenArgs genExp $ \(halfLife,start) ->
+   withGenArgs genExp $
       checkSimilarityPacked 1e-3 limitFloat
-         (SigP.exponential2 halfLife start)
-         (SigPS.exponential2 halfLife start)
+         (\(halfLife,start) -> Sig.exponential2 halfLife start)
+         (\(halfLife,start) -> SigPS.exponential2 halfLife start)
 
 exponential2Static :: Test (Float,Float) SimFloat
 exponential2Static =
-   withGenArgs genExp $ \(halfLife,start) ->
+   withGenArgs genExp $
       checkSimilarity 1e-3 limitFloat
-          (SigP.exponential2 halfLife start)
-          (Exp.causalP start <<<
-           CausalP.mapSimple Exp.parameter $*
-           SigP.constant halfLife)
+          (\(halfLife,start) -> Sig.exponential2 halfLife start)
+          (\(halfLife,start) ->
+           Exp.causal start <<<
+           Causal.map Exp.parameterPlain $*
+           Sig.constant halfLife)
 
 exponential2PackedStatic :: Test (Float,Float) SimFloat
 exponential2PackedStatic =
-   withGenArgs genExp $ \(halfLife,start) ->
+   withGenArgs genExp $
       checkSimilarity 1e-3 (limitFloat . SigStL.unpack)
-          (SigPS.exponential2 halfLife start ::
-           SigP.T (Float,Float) VectorValue)
-          (Exp.causalPackedP start <<<
-           CausalP.mapSimple Exp.parameterPacked $*
-           SigP.constant halfLife)
+         (\(halfLife,start) ->
+            SigPS.exponential2 halfLife start :: Sig.T VectorValue)
+         (\(halfLife,start) ->
+           Exp.causalPacked start <<<
+           Causal.map Exp.parameterPackedExp $*
+           Sig.constant halfLife)
 
 exponential2Controlled :: Test ((Float,Float), (Float,Float)) SimFloat
 exponential2Controlled =
@@ -136,19 +139,20 @@
       (pair genExp
          (pair (Gen.choose (0.0001, 0.001)) (Gen.choose (0, 0.99 :: Float)))) $
 
-   -- 'freq' is the LFO frequency measured at vector-rate
-   \((halfLife,start), (freq,phase)) ->
-   let lfo =
-          CausalP.mapExponential 2 halfLife $*
-          SigP.osciSimple Wave.approxSine2 phase freq
+   let lfo halfLife freq phase =
+          Causal.mapExponential 2 halfLife $*
+          Sig.osci Wave.approxSine2 phase freq
    in  checkSimilarityPacked 1e-3 limitFloat
-          (Exp.causalP start <<<
-           CausalP.mapSimple Exp.parameter $*
-           SigP.interpolateConstant
-              (TypeNum.integralFromProxy TypeNum.d4 :: Param.T p Float)
-              lfo)
-          (Exp.causalPackedP start <<<
-           CausalP.mapSimple Exp.parameterPacked $* lfo)
+          (-- 'freq' is the LFO frequency measured at vector-rate
+           \((halfLife,start), (freq,phase)) ->
+           Exp.causal start <<<
+           Causal.map Exp.parameterPlain $*
+           Sig.interpolateConstant
+              (TypeNum.integralFromProxy TypeNum.d4 :: Exp Float)
+              (lfo halfLife freq phase))
+          (\((halfLife,start), (freq,phase)) ->
+           Exp.causalPacked start <<<
+           Causal.map Exp.parameterPackedExp $* lfo halfLife freq phase)
 
 osci :: Test (Float,Float) SimFloat
 osci =
@@ -156,10 +160,9 @@
       (pair
          (Gen.choose (0.001, 0.01))
          (Gen.choose (0, 0.99))) $
-   \(freq,phase) ->
-      checkSimilarityPacked 1e-2 limitFloat
-         (SigP.osciSimple Wave.approxSine2 phase freq)
-         (SigPS.osciSimple Wave.approxSine2 phase freq)
+   checkSimilarityPacked 1e-2 limitFloat
+      (\(freq,phase) -> Sig.osci Wave.approxSine2 phase freq)
+      (\(freq,phase) -> SigPS.osci Wave.approxSine2 phase freq)
 
 
 
@@ -167,30 +170,28 @@
 limitWord32 = SVL.take signalLength
 
 limitPackedWord32 ::
-   SVL.Vector (Serial.Plain D4 Word32) -> SVL.Vector (Serial.Plain D4 Word32)
+   SVL.Vector (SerialPlain.T D4 Word32) -> SVL.Vector (SerialPlain.T D4 Word32)
 limitPackedWord32 = SVL.take (div signalLength 4)
 
 
 noise :: IO (ChunkSize -> Word32 -> CheckEquality Word32)
 noise =
-   checkEquality limitWord32
-      (SigP.noiseCore (arr id))
-      (SigP.noiseCoreAlt (arr id))
+   checkEquality limitWord32 SigCore.noise SigCore.noiseAlt
 
-noiseVector :: IO (ChunkSize -> Word32 -> CheckEquality (Serial.Plain D4 Word32))
+noiseVector ::
+   IO (ChunkSize -> Word32 -> CheckEquality (SerialPlain.T D4 Word32))
 noiseVector =
-   checkEquality limitPackedWord32
-      (SigPS.noiseCore (arr id))
-      (SigPS.noiseCoreAlt (arr id))
+   checkEquality limitPackedWord32 SigPS.noiseCore SigPS.noiseCoreAlt
 
-noiseScalarVector :: IO (ChunkSize -> Word32 -> CheckEquality (Serial.Plain D4 Word32))
+noiseScalarVector ::
+   IO (ChunkSize -> Word32 -> CheckEquality (SerialPlain.T D4 Word32))
 noiseScalarVector =
    checkEquality limitPackedWord32
-      (SigPS.noiseCore (arr id))
-      (SigPS.packSmall (SigP.noiseCore (arr id)))
+      SigPS.noiseCore
+      (SigPS.packSmall . SigCore.noise)
 
 
-tests :: [(String, IO ())]
+tests :: [(String, IO QC.Property)]
 tests =
    ("constant", checkWithParam constant) :
    ("ramp", checkWithParam ramp) :
@@ -203,7 +204,7 @@
    ("exponential2PackedStatic", checkWithParam exponential2PackedStatic) :
    ("exponential2Controlled", checkWithParam exponential2Controlled) :
    ("osci", checkWithParam osci) :
-   ("noise", quickCheck =<< noise) :
-   ("noiseVector", quickCheck =<< noiseVector) :
-   ("noiseScalarVector", quickCheck =<< noiseScalarVector) :
+   ("noise", QC.property <$> noise) :
+   ("noiseVector", QC.property <$> noiseVector) :
+   ("noiseScalarVector", QC.property <$> noiseScalarVector) :
    []
diff --git a/testsuite/Test/Synthesizer/LLVM/RingBufferForward.hs b/testsuite/Test/Synthesizer/LLVM/RingBufferForward.hs
--- a/testsuite/Test/Synthesizer/LLVM/RingBufferForward.hs
+++ b/testsuite/Test/Synthesizer/LLVM/RingBufferForward.hs
@@ -1,12 +1,10 @@
 {-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE Rank2Types #-}
 module Test.Synthesizer.LLVM.RingBufferForward (tests) where
 
-import qualified Synthesizer.LLVM.Parameter as Param
-import qualified Synthesizer.LLVM.CausalParameterized.RingBufferForward as RingBuffer
-import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import Synthesizer.LLVM.CausalParameterized.Process (($*))
+import qualified Synthesizer.LLVM.Causal.RingBufferForward as RingBuffer
+import qualified Synthesizer.LLVM.Causal.Process as Causal
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import Synthesizer.LLVM.Causal.Process (($*))
 
 import qualified Data.StorableVector.Lazy as SVL
 
@@ -15,20 +13,23 @@
          (Test, checkWithParam, arg, pair, triple, withGenArgs)
 import Test.Synthesizer.LLVM.Utility
          (CheckEquality, CheckEquality2, checkEquality, checkEquality2,
-          genRandomVectorParam, randomSignal)
+          genRandomVectorParam, randomStorableVectorLoop)
 
-import Control.Applicative (pure)
+import qualified Control.Arrow as Arrow
+import Control.Arrow ((<<^))
+import Control.Applicative ((<$>))
 
-import qualified LLVM.Extra.Arithmetic as A
+import qualified LLVM.DSL.Expression as Expr
 
-import qualified LLVM.Core as LLVM
-import LLVM.Core (Value)
+import qualified LLVM.Extra.Multi.Value as MultiValue
 
 import Foreign.Storable (Storable)
 
 import qualified System.Random as Rnd
 import Data.Word (Word, Word32)
 
+import qualified Test.QuickCheck as QC
+
 import NumericPrelude.Numeric
 import NumericPrelude.Base
 
@@ -43,65 +44,67 @@
 limitFloat = SVL.take signalLength
 
 
-trackId :: Test (Int, Word32) EquFloat
+trackId :: Test (Word, Word32) EquFloat
 trackId =
    withGenArgs (pair (Gen.choose (1,1000)) Gen.arbitrary) $
-         \(bufferSize, seed) ->
-     let noise = SigP.noise seed 1
+     let noise seed = Sig.noise seed 1
      in checkEquality limitFloat
-          noise
-          (CausalP.mapSimple (RingBuffer.index A.zero) $*
-           RingBuffer.track bufferSize noise)
+            (\(_bufferSize, seed) -> noise seed)
+            (\(bufferSize, seed) ->
+               RingBuffer.mapIndex zero
+                  $* RingBuffer.track bufferSize (noise seed))
 
-trackTail :: Test (Int, Word32) EquFloat
+trackTail :: Test (Word, Word32) EquFloat
 trackTail =
    withGenArgs (pair (Gen.choose (2,1000)) Gen.arbitrary) $
-         \(bufferSize, seed) ->
-     let noise = SigP.noise seed 1
+     let noise seed = Sig.noise seed 1
      in checkEquality limitFloat
-          (SigP.tail noise)
-          (CausalP.mapSimple (RingBuffer.index A.one) $*
-           RingBuffer.track bufferSize noise)
+            (\(_bufferSize, seed) -> Sig.tail $ noise seed)
+            (\(bufferSize, seed) ->
+               RingBuffer.mapIndex one
+                  $* RingBuffer.track bufferSize (noise seed))
 
-trackDrop :: Test (Int, Word32) EquFloat
+trackDrop :: Test (Word, Word32) EquFloat
 trackDrop =
    withGenArgs (pair (Gen.choose (0,1000)) Gen.arbitrary) $
-         \(n, seed) ->
-     let noise = SigP.noise seed 1
+     let noise seed = Sig.noise seed 1
      in checkEquality limitFloat
-          (SigP.drop n noise)
-          (CausalP.map RingBuffer.index (fmap (fromIntegral :: Int -> Word) n) $*
-           RingBuffer.track (fmap succ n) noise)
+          (\(n, seed) -> Sig.drop n $ noise seed)
+          (\(n, seed) ->
+             RingBuffer.mapIndex n $* RingBuffer.track (n+1) (noise seed))
 
-randomSkips :: Param.T p (Int, Rnd.StdGen) -> SigP.T p (Value Word)
-randomSkips = randomSignal (0,10::Word)
+randomSkips :: (Int, Rnd.StdGen) -> SVL.Vector Word
+randomSkips = randomStorableVectorLoop (0,10)
 
 trackSkip :: Test ((Int, Rnd.StdGen), Word32) EquFloat
 trackSkip =
    withGenArgs (pair (arg genRandomVectorParam) Gen.arbitrary) $
-      \(sk, seed) ->
-   let skips = randomSkips sk
-       noise = SigP.noise seed 1
-   in  checkEquality limitFloat
-          (CausalP.skip noise $* skips)
-          (CausalP.mapSimple (RingBuffer.index A.one) $*
-           (RingBuffer.trackSkip 1 noise $* skips))
+   let noise seed = Sig.noise seed 1
+   in (\f chunkSize (sk, seed) -> f chunkSize (randomSkips sk, seed))
+      <$>
+      checkEquality limitFloat
+         (\(skips, seed) -> Causal.skip (noise seed) $* skips)
+         (\(skips, seed) ->
+            RingBuffer.mapIndex one
+               $* (RingBuffer.trackSkip 1 (noise seed) $* skips))
 
 trackSkip1 :: Test (Word, Word32) EquFloat
 trackSkip1 =
-   let bufferSize :: Int
-       bufferSize = 1000
+   let bufferSize = 1000
    in  withGenArgs
          (pair
             (Gen.choose (0, fromIntegral bufferSize - 1))
             Gen.arbitrary) $
-         \(k, seed) ->
-            let noise = SigP.noise seed 1
+
+            let noise seed = Sig.noise seed 1
             in  checkEquality limitFloat
-                  (CausalP.map RingBuffer.index k $*
-                   (RingBuffer.track (pure bufferSize) noise))
-                  (CausalP.map RingBuffer.index k $*
-                   (RingBuffer.trackSkip (pure bufferSize) noise $* 1))
+                  (\(k, seed) ->
+                     RingBuffer.mapIndex k $*
+                     RingBuffer.track (Expr.cons bufferSize) (noise seed))
+                  (\(k, seed) ->
+                     RingBuffer.mapIndex k $*
+                     (RingBuffer.trackSkip (Expr.cons bufferSize) (noise seed)
+                        $* 1))
 
 trackSkipHold ::
    Test ((Int, Rnd.StdGen), Word, Word32) (CheckEquality2 Bool Float)
@@ -112,17 +115,24 @@
             (arg genRandomVectorParam)
             (Gen.choose (0, fromIntegral bufferSize - 1))
             Gen.arbitrary) $
-         \(sk, k, seed) ->
-            let skips = randomSkips sk
-                noise = SigP.noise seed 1
-            in  checkEquality2 limitFloat limitFloat
-                  (fmap ((,) (LLVM.valueOf True)) $
-                   (CausalP.map RingBuffer.index k $*
-                    (RingBuffer.trackSkip (pure bufferSize) noise $* skips)))
-                  (CausalP.map
-                      (\ki ((b,_s),buf) -> fmap ((,) b) $ RingBuffer.index ki buf) k $*
-                   (RingBuffer.trackSkipHold (pure bufferSize) noise $* skips))
 
+            let noise seed = Sig.noise seed 1
+            in (\f chunkSize (sk, k, seed) ->
+                  f chunkSize (randomSkips sk, k, seed))
+               <$>
+               checkEquality2 limitFloat limitFloat
+                  (\(skips, k, seed) ->
+                   (,) (MultiValue.cons True) <$>
+                   (RingBuffer.mapIndex k $*
+                    (RingBuffer.trackSkip (Expr.cons bufferSize) (noise seed)
+                        $* skips)))
+                  (\(skips, k, seed) ->
+                   (Arrow.second (RingBuffer.mapIndex k)
+                        <<^ (\((b,_s),buf) -> (b,buf)))
+                   $*
+                   (RingBuffer.trackSkipHold (Expr.cons bufferSize) (noise seed)
+                        $* skips))
+
 {-
 To do:
 
@@ -130,7 +140,7 @@
 -}
 
 
-tests :: [(String, IO ())]
+tests :: [(String, IO QC.Property)]
 tests =
    ("trackId", checkWithParam trackId) :
    ("trackTail", checkWithParam trackTail) :
diff --git a/testsuite/Test/Synthesizer/LLVM/Utility.hs b/testsuite/Test/Synthesizer/LLVM/Utility.hs
--- a/testsuite/Test/Synthesizer/LLVM/Utility.hs
+++ b/testsuite/Test/Synthesizer/LLVM/Utility.hs
@@ -1,13 +1,18 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module Test.Synthesizer.LLVM.Utility where
 
-import qualified Synthesizer.LLVM.Parameterized.SignalPacked as SigPS
-import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
-import qualified Synthesizer.LLVM.Parameter as Param
-import qualified Synthesizer.LLVM.Plug.Output as POut
-import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
+import qualified Synthesizer.LLVM.Causal.Render as CausalRender
+import qualified Synthesizer.LLVM.Generator.Render as Render
+import qualified Synthesizer.LLVM.Generator.SignalPacked as SigPS
+import qualified Synthesizer.LLVM.Generator.Signal as Sig
+import qualified Synthesizer.LLVM.Frame.SerialVector.Code as SerialCode
+import Synthesizer.LLVM.Causal.Process ()
 
+import qualified Synthesizer.CausalIO.Process as PIO
+import qualified Synthesizer.Causal.Class as CausalClass
+import qualified Synthesizer.Generic.Signal as SigG
 import qualified Synthesizer.State.Signal as SigS
 import qualified Synthesizer.Zip as Zip
 
@@ -19,9 +24,8 @@
 import Data.StorableVector.Lazy (ChunkSize)
 import Foreign.Storable (Storable)
 
-import qualified LLVM.Extra.Storable as Storable
-import qualified LLVM.Extra.Tuple as Tuple
-import qualified LLVM.Core as LLVM
+import qualified LLVM.Extra.Multi.Value.Storable as Storable
+import qualified LLVM.Extra.Multi.Value as MultiValue
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
@@ -31,6 +35,8 @@
 
 import qualified Test.QuickCheck as QC
 
+import qualified System.Unsafe as Unsafe
+
 import qualified Algebra.RealRing as RealRing
 import qualified Algebra.Absolute as Absolute
 
@@ -54,30 +60,28 @@
 randomStorableVectorLoop range param =
    SVL.cycle $ SVL.fromChunks [randomStorableVector range param]
 
-randomSignal ::
-   (Storable.C a, Tuple.ValueOf a ~ al, Random a) =>
-   (a, a) -> Param.T p (Int, StdGen) -> SigP.T p al
-randomSignal range p =
-   SigP.fromStorableVectorLazy (randomStorableVectorLoop range <$> p)
 
-
 render ::
-   (Storable.C a, Tuple.ValueOf a ~ al) =>
+   (Render.RunArg p) =>
+   (Storable.C a, MultiValue.T a ~ al) =>
    (SVL.Vector a -> sig) ->
-   SigP.T p al -> IO (ChunkSize -> p -> sig)
+   (Render.DSLArg p -> Sig.T al) -> IO (ChunkSize -> p -> sig)
 render limit sig =
-   fmap (\func chunkSize -> limit . func chunkSize) $ SigP.runChunky sig
+   fmap (\func chunkSize -> limit . func chunkSize) $ Render.run sig
 
 render2 ::
-   (Storable.C a, Tuple.ValueOf a ~ al) =>
-   (Storable.C b, Tuple.ValueOf b ~ bl) =>
+   (Render.RunArg p) =>
+   (Storable.C a, MultiValue.T a ~ al) =>
+   (Storable.C b, MultiValue.T b ~ bl) =>
    ((SVL.Vector a, SVL.Vector b) -> sig) ->
-   SigP.T p (al, bl) -> IO (ChunkSize -> p -> sig)
-render2 limit sig =
-   fmap (\func chunkSize ->
-            limit . mapPair (SVL.fromChunks, SVL.fromChunks) .
-            unzip . map (\(Zip.Cons a b) -> (a,b)) . func chunkSize) $
-   SigP.runChunkyPlugged sig POut.deflt
+   (Render.DSLArg p -> Sig.T (al, bl)) -> IO (ChunkSize -> p -> sig)
+render2 limit sig = do
+   proc <- CausalRender.run (CausalClass.fromSignal . sig)
+   return $ \(SVL.ChunkSize chunkSize) p ->
+      limit . mapPair (SVL.fromChunks, SVL.fromChunks) .
+      unzip . map (\(Zip.Cons a b) -> (a,b)) $
+      Unsafe.performIO (PIO.runCont (proc p)) (const [])
+         (repeat $ SigG.LazySize chunkSize)
 
 
 data CheckSimilarityState a =
@@ -94,10 +98,11 @@
 
 {-# INLINE checkSimilarityState #-}
 checkSimilarityState ::
-   (RealRing.C a, Storable.C a, Tuple.ValueOf a ~ av) =>
+   (Render.RunArg p) =>
+   (RealRing.C a, Storable.C a, MultiValue.T a ~ av) =>
    a ->
    (SVL.Vector a -> SVL.Vector a) ->
-   SigP.T p av ->
+   (Render.DSLArg p -> Sig.T av) ->
    (p -> SigS.T a) ->
    IO (ChunkSize -> p -> CheckSimilarityState a)
 checkSimilarityState tol limit gen0 sig1 =
@@ -110,7 +115,9 @@
 data CheckSimilarity a =
    CheckSimilarity a (SVL.Vector a) (SVL.Vector a)
 
-instance (Storable a, Ord a, Absolute.C a) => QC.Testable (CheckSimilarity a) where
+instance
+   (Storable a, Ord a, Absolute.C a) =>
+      QC.Testable (CheckSimilarity a) where
    property (CheckSimilarity tol xs ys) =
       QC.property $
          SigS.foldR (&&) True $
@@ -121,11 +128,13 @@
 
 {-# INLINE checkSimilarity #-}
 checkSimilarity ::
+   (Render.RunArg p) =>
    (RealRing.C b, Storable.C b,
-    Storable.C a, Tuple.ValueOf a ~ av) =>
+    Storable.C a, MultiValue.T a ~ av) =>
    b ->
    (SVL.Vector a -> SVL.Vector b) ->
-   SigP.T p av -> SigP.T p av ->
+   (Render.DSLArg p -> Sig.T av) ->
+   (Render.DSLArg p -> Sig.T av) ->
    IO (ChunkSize -> p -> CheckSimilarity b)
 checkSimilarity tol limit gen0 gen1 =
    liftM2
@@ -135,13 +144,14 @@
       (render limit gen1)
 
 checkSimilarityPacked ::
+   (Render.RunArg p) =>
    Float ->
    (SVL.Vector Float -> SVL.Vector Float) ->
-   SigP.T p (LLVM.Value Float) ->
-   SigP.T p (Serial.Value TypeNum.D4 Float) ->
+   (Render.DSLArg p -> Sig.T (MultiValue.T Float)) ->
+   (Render.DSLArg p -> Sig.T (SerialCode.Value TypeNum.D4 Float)) ->
    IO (ChunkSize -> p -> CheckSimilarity Float)
 checkSimilarityPacked tol limit scalar vector =
-   checkSimilarity tol limit scalar (SigPS.unpack vector)
+   checkSimilarity tol limit scalar (SigPS.unpack . vector)
 
 
 {- |
@@ -158,9 +168,11 @@
    property (CheckEqualityGen x y) = QC.property (x==y)
 
 checkEquality ::
-   (Eq a, Storable.C a, Tuple.ValueOf a ~ av) =>
+   (Render.RunArg p) =>
+   (Eq a, Storable.C a, MultiValue.T a ~ av) =>
    (SVL.Vector a -> SVL.Vector a) ->
-   SigP.T p av -> SigP.T p av ->
+   (Render.DSLArg p -> Sig.T av) ->
+   (Render.DSLArg p -> Sig.T av) ->
    IO (ChunkSize -> p -> CheckEquality a)
 checkEquality limit gen0 gen1 =
    liftM2
@@ -170,11 +182,13 @@
       (render limit gen1)
 
 checkEquality2 ::
-   (Eq a, Storable.C a, Tuple.ValueOf a ~ al) =>
-   (Eq b, Storable.C b, Tuple.ValueOf b ~ bl) =>
+   (Render.RunArg p) =>
+   (Eq a, Storable.C a, MultiValue.T a ~ al) =>
+   (Eq b, Storable.C b, MultiValue.T b ~ bl) =>
    (SVL.Vector a -> SVL.Vector a) ->
    (SVL.Vector b -> SVL.Vector b) ->
-   SigP.T p (al,bl) -> SigP.T p (al,bl) ->
+   (Render.DSLArg p -> Sig.T (al,bl)) ->
+   (Render.DSLArg p -> Sig.T (al,bl)) ->
    IO (ChunkSize -> p -> CheckEquality2 a b)
 checkEquality2 limitA limitB gen0 gen1 =
    liftM2
