diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+1.2.3 - 100131
+* added externalMulti to handle events that can fire several times within a superstep
+* added a cache to the noise signal for safety reasons, so it lives in SignalGen now
+
 1.2.2 - 100115
 * added noise signals and the getRandom primitive (using mersenne-random)
 
diff --git a/FRP/Elerea/Experimental/Delayed.hs b/FRP/Elerea/Experimental/Delayed.hs
--- a/FRP/Elerea/Experimental/Delayed.hs
+++ b/FRP/Elerea/Experimental/Delayed.hs
@@ -31,6 +31,7 @@
     , SignalGen
     , start
     , external
+    , externalMulti
     , delay
     , stateful
     , transfer
@@ -42,6 +43,7 @@
     ) where
 
 import Control.Applicative
+import Control.Concurrent.MVar
 import Control.Monad
 import Control.Monad.Fix
 import Data.IORef
@@ -208,6 +210,26 @@
   ref <- newIORef x
   return (S (const (readIORef ref)), writeIORef ref)
 
+-- | An event-like signal that can be fed through the sink function
+-- returned.  The signal carries a list of values fed in since the
+-- last sampling, i.e. it is constantly [] if the sink is never
+-- invoked.  The order of elements is reversed, so the last value
+-- passed to the sink is the head of the list.  Note that unlike
+-- 'external' this function only returns a generator to be used within
+-- the expression constructing the top-level stream, and this
+-- generator can only be used once.
+externalMulti :: IO (SignalGen p (Signal p [a]), a -> IO ()) -- ^ a generator for the event signal and the associated sink
+externalMulti = do
+  var <- newMVar []
+  return (SG $ \pool -> do
+             let sig = S $ const (readMVar var)
+             update <- mkWeak sig (const (return ()),takeMVar var >> putMVar var []) Nothing
+             modifyIORef pool (update:)
+             return sig
+         ,\val -> do  vals <- takeMVar var
+                      putMVar var (val:vals)
+         )
+
 -- | A pure stateful signal.  The initial state is the first output,
 -- and every following output is calculated from the previous one and
 -- the value of the global parameter.
@@ -254,12 +276,9 @@
 
   addSignal sample age ref pool
 
--- | A random signal.  For efficiency reasons it is not guaranteed to
--- read the same value when sampled several times in the same
--- superstep.  If you need consistent noise input, you can produce it
--- through an 'external' signal from whatever source you prefer.
-noise :: MTRandom a => Signal p a
-noise = S (const randomIO)
+-- | A random signal.
+noise :: MTRandom a => SignalGen p (Signal p a)
+noise = memo (S (const randomIO))
 
 -- | A random source within the 'SignalGen' monad.
 getRandom :: MTRandom a => SignalGen p a
diff --git a/FRP/Elerea/Experimental/Param.hs b/FRP/Elerea/Experimental/Param.hs
--- a/FRP/Elerea/Experimental/Param.hs
+++ b/FRP/Elerea/Experimental/Param.hs
@@ -35,6 +35,7 @@
     , SignalGen
     , start
     , external
+    , externalMulti
     , delay
     , stateful
     , transfer
@@ -46,6 +47,7 @@
     ) where
 
 import Control.Applicative
+import Control.Concurrent.MVar
 import Control.Monad
 import Control.Monad.Fix
 import Data.IORef
@@ -209,6 +211,26 @@
   ref <- newIORef x
   return (S (const (readIORef ref)), writeIORef ref)
 
+-- | An event-like signal that can be fed through the sink function
+-- returned.  The signal carries a list of values fed in since the
+-- last sampling, i.e. it is constantly [] if the sink is never
+-- invoked.  The order of elements is reversed, so the last value
+-- passed to the sink is the head of the list.  Note that unlike
+-- 'external' this function only returns a generator to be used within
+-- the expression constructing the top-level stream, and this
+-- generator can only be used once.
+externalMulti :: IO (SignalGen p (Signal p [a]), a -> IO ()) -- ^ a generator for the event signal and the associated sink
+externalMulti = do
+  var <- newMVar []
+  return (SG $ \pool -> do
+             let sig = S $ const (readMVar var)
+             update <- mkWeak sig (const (return ()),takeMVar var >> putMVar var []) Nothing
+             modifyIORef pool (update:)
+             return sig
+         ,\val -> do  vals <- takeMVar var
+                      putMVar var (val:vals)
+         )
+
 -- | A pure stateful signal.  The initial state is the first output,
 -- and every following output is calculated from the previous one and
 -- the value of the global parameter.
@@ -243,12 +265,9 @@
 
   addSignal sample age ref pool
 
--- | A random signal.  For efficiency reasons it is not guaranteed to
--- read the same value when sampled several times in the same
--- superstep.  If you need consistent noise input, you can produce it
--- through an 'external' signal from whatever source you prefer.
-noise :: MTRandom a => Signal p a
-noise = S (const randomIO)
+-- | A random signal.
+noise :: MTRandom a => SignalGen p (Signal p a)
+noise = memo (S (const randomIO))
 
 -- | A random source within the 'SignalGen' monad.
 getRandom :: MTRandom a => SignalGen p a
diff --git a/FRP/Elerea/Experimental/Simple.hs b/FRP/Elerea/Experimental/Simple.hs
--- a/FRP/Elerea/Experimental/Simple.hs
+++ b/FRP/Elerea/Experimental/Simple.hs
@@ -127,6 +127,7 @@
     , SignalGen
     , start
     , external
+    , externalMulti
     , delay
     , generator
     , memo
@@ -137,6 +138,7 @@
     ) where
 
 import Control.Applicative
+import Control.Concurrent.MVar
 import Control.Monad
 import Control.Monad.Fix
 import Data.IORef
@@ -295,6 +297,26 @@
   ref <- newIORef x
   return (S (readIORef ref), writeIORef ref)
 
+-- | An event-like signal that can be fed through the sink function
+-- returned.  The signal carries a list of values fed in since the
+-- last sampling, i.e. it is constantly [] if the sink is never
+-- invoked.  The order of elements is reversed, so the last value
+-- passed to the sink is the head of the list.  Note that unlike
+-- 'external' this function only returns a generator to be used within
+-- the expression constructing the top-level stream, and this
+-- generator can only be used once.
+externalMulti :: IO (SignalGen (Signal [a]), a -> IO ()) -- ^ a generator for the event signal and the associated sink
+externalMulti = do
+  var <- newMVar []
+  return (SG $ \pool -> do
+             let sig = S $ readMVar var
+             update <- mkWeak sig (return (),takeMVar var >> putMVar var []) Nothing
+             modifyIORef pool (update:)
+             return sig
+         ,\val -> do  vals <- takeMVar var
+                      putMVar var (val:vals)
+         )
+
 -- | A pure stateful signal.  The initial state is the first output,
 -- and every subsequent state is derived from the preceding one by
 -- applying a pure transformation.  It is equivalent to the following
@@ -325,12 +347,9 @@
          -> SignalGen (Signal a)
 transfer x0 f s = mfix $ \sig -> liftA2 f s <$> delay x0 sig
 
--- | A random signal.  For efficiency reasons it is not guaranteed to
--- read the same value when sampled several times in the same
--- superstep.  If you need consistent noise input, you can produce it
--- through an 'external' signal from whatever source you prefer.
-noise :: MTRandom a => Signal a
-noise = S randomIO
+-- | A random signal.
+noise :: MTRandom a => SignalGen (Signal a)
+noise = memo (S randomIO)
 
 -- | A random source within the 'SignalGen' monad.
 getRandom :: MTRandom a => SignalGen a
diff --git a/elerea.cabal b/elerea.cabal
--- a/elerea.cabal
+++ b/elerea.cabal
@@ -1,5 +1,5 @@
 Name:                elerea
-Version:             1.2.2
+Version:             1.2.3
 Cabal-Version:       >= 1.2
 Synopsis:            A minimalistic FRP library
 Category:            reactivity, FRP
