diff --git a/mediabus.cabal b/mediabus.cabal
--- a/mediabus.cabal
+++ b/mediabus.cabal
@@ -1,5 +1,5 @@
 name: mediabus
-version: 0.3.2.1
+version: 0.3.3.0
 cabal-version: >=1.10
 build-type: Simple
 license: BSD3
@@ -52,10 +52,10 @@
         Data.MediaBus.Media.Channels
         Data.MediaBus.Media.Discontinous
         Data.MediaBus.Media.Media
-        Data.MediaBus.Media.Reframe
         Data.MediaBus.Media.Samples
         Data.MediaBus.Media.Segment
         Data.MediaBus.Media.Stream
+        Data.MediaBus.Media.SyncStream
         Data.MediaBus.Transport.Udp
     build-depends:
         QuickCheck <2.10,
@@ -150,6 +150,7 @@
     other-modules:
         Data.MediaBus.Conduit.Audio.Raw.ResampleSpec
         Data.MediaBus.Media.BufferSpec
+        Data.MediaBus.Media.SyncStreamSpec
         Data.MediaBus.Conduit.SegmentSpec
         Data.MediaBus.Conduit.ReorderSpec
         Data.MediaBus.Conduit.StreamSpec
diff --git a/specs/Data/MediaBus/Media/SyncStreamSpec.hs b/specs/Data/MediaBus/Media/SyncStreamSpec.hs
new file mode 100644
--- /dev/null
+++ b/specs/Data/MediaBus/Media/SyncStreamSpec.hs
@@ -0,0 +1,94 @@
+module Data.MediaBus.Media.SyncStreamSpec
+  ( spec
+  ) where
+
+import Control.Lens
+import Control.Monad.State
+import Data.Function
+import Data.MediaBus
+import Debug.Trace
+import Test.Hspec
+import Test.QuickCheck
+
+newtype FakePayload = FP
+  { fakeDuration :: Ticks64At8000
+  } deriving (Eq, Show, Num, Arbitrary, Ord)
+
+instance HasDuration FakePayload where
+  getDuration = view (to fakeDuration . nominalDiffTime)
+
+spec :: Spec
+spec =
+  describe "setSequenceNumbersAndTimestamps" $ do
+    it "increases the sequence number by one (only) for each frame" $
+      let prop :: (NonEmptyList (SyncStream () () FakePayload)) -> Bool
+          prop (NonEmpty inStr) =
+            let expectedLastSeqNum =
+                  let isNext (MkStream (Next _)) = True
+                      isNext _ = False
+                  in max 0 (fromIntegral (length (filter isNext inStr)) - 1)
+                actualLastSeqNum =
+                  let outStr =
+                        let z :: (SeqNum16, Ticks64At8000)
+                            z = (0, 0)
+                        in evalState
+                             (mapM
+                                (state . setSequenceNumbersAndTimestamps)
+                                inStr)
+                             z
+                  in case last outStr of
+                       MkStream (Next f) -> f ^. seqNum
+                       MkStream (Start f) -> max 0 (f ^. seqNum - 1)
+            in expectedLastSeqNum == actualLastSeqNum
+      in property prop
+    it "increases the sequence number monotonic" $
+      let prop :: (NonEmptyList (SyncStream () () FakePayload)) -> Bool
+          prop (NonEmpty inStr) =
+            let seqNumDiffs =
+                  let outFrames =
+                        let isNext (MkStream (Next _)) = True
+                            isNext _ = False
+                            outStr =
+                              let z :: (SeqNum16, Ticks64At8000)
+                                  z = (0, 0)
+                              in evalState
+                                   (mapM
+                                      (state . setSequenceNumbersAndTimestamps)
+                                      inStr)
+                                   z
+                        in filter isNext outStr
+                  in zipWith ((-) `on` (view seqNum)) (drop 1 outFrames) outFrames
+            in all (== 1) seqNumDiffs
+      in property prop
+    it "increases the timestamps by the duration of each frame" $
+      let prop :: (NonEmptyList (SyncStream () () FakePayload)) -> Bool
+          prop (NonEmpty inStr) =
+            let isNext (MkStream (Next _)) = True
+                isNext _ = False
+                outFrames :: [Stream () SeqNum16 Ticks64At8000 () FakePayload]
+                outFrames =
+                  let outStr =
+                        let z :: (SeqNum16, Ticks64At8000)
+                            z = (0, MkTicks 0)
+                        in evalState
+                             (mapM
+                                (state . setSequenceNumbersAndTimestamps)
+                                inStr)
+                             z
+                  in filter isNext outStr
+                timestamps = map (view timestamp) outFrames
+                expectedTimestamps :: [Ticks64At8000]
+                expectedTimestamps =
+                  let inFramesWithoutLast =
+                        (filter isNext inStr)
+                      inDurations =
+                        map (view (from nominalDiffTime) . getDuration)
+                        inFramesWithoutLast
+
+                  in scanl (+) 0 inDurations
+            in if and (zipWith (==) timestamps expectedTimestamps)
+                 then True
+                 else traceShow ( timestamps
+                                , expectedTimestamps
+                                , outFrames) False
+      in property prop
diff --git a/src/Data/MediaBus.hs b/src/Data/MediaBus.hs
--- a/src/Data/MediaBus.hs
+++ b/src/Data/MediaBus.hs
@@ -36,8 +36,8 @@
 import Data.MediaBus.Media.Channels as X
 import Data.MediaBus.Media.Discontinous as X
 import Data.MediaBus.Media.Media as X
-import Data.MediaBus.Media.Reframe as X
 import Data.MediaBus.Media.Samples as X
 import Data.MediaBus.Media.Segment as X
 import Data.MediaBus.Media.Stream as X
+import Data.MediaBus.Media.SyncStream as X
 import Data.MediaBus.Transport.Udp as X
diff --git a/src/Data/MediaBus/Media/Reframe.hs b/src/Data/MediaBus/Media/Reframe.hs
deleted file mode 100644
--- a/src/Data/MediaBus/Media/Reframe.hs
+++ /dev/null
@@ -1,158 +0,0 @@
--- | This module contains functions and types for reframing the sequence number
---   and timestamps of 'Frame's.
---
---   This means that this module will allow you to record a set of incoming
---   frames using 'pushFrame'. Whenever you want to extract the timing and
---   sequence number information of the next frame with a given duration,
---   use 'generateFrame'.
-module Data.MediaBus.Media.Reframe
-  ( initialReframerState
-  , runReframer
-  , pushStartFrame
-  , pushFrame
-  , PushFrameError(..)
-  , nextFrameAvailableDuration
-  , nextFrameTimestamp
-  , generateFrame
-  , type ReframerT
-  , ReframerSt()
-  , ReframeError(..)
-  , mkReFrameError
-  ) where
-
-import Control.Exception
-import Control.Monad
-import Control.Monad.Trans.State.Strict as State
-import Data.MediaBus.Media.Stream
-import Data.Typeable
-
--- | Create an empty initial state.
-initialReframerState
-  :: (Num d, Num s)
-  => ReframerSt s d
-initialReframerState = MkTimeFrame 0 0 0
-
--- | Run state 'ReframerSt' state transformer.
-runReframer
-  :: Monad m
-  => ReframerT m s d a -> ReframerSt s d -> m (a, ReframerSt s d)
-runReframer = runStateT
-
--- | Reset the current timing and sequence number, and start with the given
---   start time.
-pushStartFrame
-  :: (Num d, Monad m)
-  => d -> ReframerT m s d ()
-pushStartFrame d = do
-  (MkTimeFrame _ s _) <- State.get
-  State.put (MkTimeFrame d s d)
-
--- | Increase the available duration by the duration in the frame,  iff the
---   timestamp of the given frame matches exactly the timestamp after the end
---   of the available period, otherwise do nothing with the state and return
---   'True'.
-pushFrame
-  :: (Num d, Monad m, Eq d, Ord d)
-  => Frame s d d -> ReframerT m s d (Maybe PushFrameError)
-pushFrame (MkFrame ts _ dur) = do
-  (MkTimeFrame startTs nextSeq endTs) <- State.get
-  let endTs' = ts + dur
-  when (ts == endTs) (State.put (MkTimeFrame startTs nextSeq endTs'))
-  return
-    (if | ts < endTs && endTs' < endTs -> Just InputFrameIsLate
-        | ts < endTs && endTs' >= endTs -> Just InputFrameOverlaps
-        | ts > endTs -> Just InputFrameIsEarly
-        | ts == endTs -> Nothing)
-
--- | Specifies in what way 'pushFrame' failed
-data PushFrameError
-  = InputFrameIsLate -- ^ The input frame ends before '_endTs'
-  | InputFrameOverlaps -- ^ The input frame starts before, and ends after '_endTs'
-  | InputFrameIsEarly -- ^ The input frame begins after '_endTs'
-  deriving (Eq, Ord, Show, Enum)
-
--- | Return the duration of the frames recorded with 'pushFrame'.
-nextFrameAvailableDuration
-  :: (Num d, Monad m)
-  => ReframerT m s d d
-nextFrameAvailableDuration = do
-  (MkTimeFrame startTs _ endTs) <- State.get
-  return (endTs - startTs)
-
--- | Return the timestamp of the frame being build. .
-nextFrameTimestamp
-  :: (Num d, Monad m)
-  => ReframerT m s d d
-nextFrameTimestamp = do
-  (MkTimeFrame startTs _ _) <- State.get
-  return startTs
-
--- | Try to create a frame with the given duration, and update the state
---   accordingly, the actual duration, that was available is
---   put into the payload field of the frame returned.
---   The start time stamp of the next frame
---   is always incremented by the @wantedDureation@ regardless of wether it was
---   available.
-generateFrame
-  :: (Num s, Num d, Monad m, Eq d, Ord d, Show d)
-  => d -> ReframerT m s d (Frame s d d)
-generateFrame wantedDuration = do
-  (MkTimeFrame startTs nextSeq endTs) <- State.get
-  available <- nextFrameAvailableDuration
-  let endTs' = max (startTs + wantedDuration) endTs
-  State.put (MkTimeFrame (startTs + wantedDuration) (nextSeq + 1) endTs')
-  return (MkFrame startTs nextSeq (wantedDuration `min` available))
-
--- | Reframer state.
-data ReframerSt s d = MkTimeFrame
-  { _startTs :: !d
-  , _nextSeqNum :: !s
-  , _endTs :: !d
-  } deriving (Typeable)
-
-instance (Show s, Show d) =>
-         Show (ReframerSt s d) where
-  showsPrec d MkTimeFrame {_startTs, _nextSeqNum, _endTs} =
-    showParen
-      (d > 10)
-      (showString "reframer-state: " .
-       showString "start: " .
-       showsPrec 11 _startTs .
-       showString ", end: " .
-       showsPrec 11 _endTs . showString ", next-sn: " . showsPrec 11 _nextSeqNum)
-
--- | The 'ReframerSt' 'StateT' transformer
-type ReframerT m s d a = StateT (ReframerSt s d) m a
-
--- | The exception type for 'encodeLinearToAacC'
-data ReframeError s d = MkReframeError
-  { reframeError :: String
-  , reframeErrorRequestedOutput :: Maybe d
-  , reframeErrorSt :: ReframerSt s d
-  } deriving (Typeable)
-
-instance (Show s, Show d) =>
-         Show (ReframeError s d) where
-  showsPrec d MkReframeError { reframeError
-                             , reframeErrorRequestedOutput
-                             , reframeErrorSt
-                             } =
-    showParen
-      (d > 10)
-      (showString "reframe-error: " .
-       showsPrec 11 reframeError .
-       maybe
-         id
-         (\ro -> showString ", requested: " . showsPrec 11 ro)
-         reframeErrorRequestedOutput .
-       showString ", " . showsPrec 11 reframeErrorSt)
-
-instance (Show s, Typeable s, Show d, Typeable d) =>
-         Exception (ReframeError s d)
-
--- | Utility function to generate a 'ReframeError' with the current state.
-mkReFrameError
-  :: Monad m
-  => String -> Maybe d -> ReframerT m s d (ReframeError s d)
-mkReFrameError msg requestedOutputDuration =
-  MkReframeError msg requestedOutputDuration <$> State.get
diff --git a/src/Data/MediaBus/Media/SyncStream.hs b/src/Data/MediaBus/Media/SyncStream.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/MediaBus/Media/SyncStream.hs
@@ -0,0 +1,44 @@
+-- | Naturally ordered 'Stream's.
+-- A 'Stream' without sequence numbers and timestamps has no means to represent
+-- 'Frame's that have varying sequence numbers or timestamps, hence they cannot
+-- be part of a stream that is not perfectly synchronized, therefore when consuming
+-- such 'Stream' values, the corresponding callers must work under the assumption
+-- that the frames are perfectly synchronous.
+module Data.MediaBus.Media.SyncStream
+  ( type SyncStream
+  , assumeSynchronized
+  , setSequenceNumbersAndTimestamps
+  ) where
+
+import Data.MediaBus.Basics.Series
+import Data.MediaBus.Basics.Ticks
+import Data.MediaBus.Media.Stream
+
+-- | A 'Stream' without a meaningful sequence number or timestamp.
+type SyncStream i p c = Stream i () () p c
+
+-- | Convert a 'Stream' to a 'SyncStream' by simply /forgetting/ the sequence
+-- numbers and timestamps of the input. This expresses the assumption that the
+-- 'Frame's are either perfectly lined sequential or that this doesn't matter
+-- at all.
+assumeSynchronized :: Stream i s t p c -> SyncStream i p c
+assumeSynchronized (MkStream (Start (MkFrameCtx i _ _ p))) =
+  MkStream (Start (MkFrameCtx i () () p))
+assumeSynchronized (MkStream (Next (MkFrame _ _ c))) =
+  MkStream (Next (MkFrame () () c))
+
+-- | Set sequence numbers and timestamps.
+-- Increment the sequence numbers starting from @0@ for every frame.
+-- Start the timestamp at @0@ and add the 'Frame' duration of the 'Next'
+-- frame in the stream.
+-- This function has the signature required to turn it into a 'State' monad.
+setSequenceNumbersAndTimestamps
+  :: (Num s, CanBeTicks r t, HasDuration c)
+  => SyncStream i p c
+  -> (s, Ticks r t)
+  -> (Stream i s (Ticks r t) p c, (s, Ticks r t))
+setSequenceNumbersAndTimestamps (MkStream (Next (MkFrame _t _s !c))) (nextS, nextT) =
+  ( MkStream (Next (MkFrame nextT nextS c))
+  , (nextS + 1, nextT + getDurationTicks c))
+setSequenceNumbersAndTimestamps (MkStream (Start (MkFrameCtx i _t _s p))) (nextS, nextT) =
+  ((MkStream (Start (MkFrameCtx i nextT nextS p))), (nextS, nextT))
