diff --git a/mutable-iter.cabal b/mutable-iter.cabal
--- a/mutable-iter.cabal
+++ b/mutable-iter.cabal
@@ -1,5 +1,5 @@
 Name:                mutable-iter
-Version:             0.6
+Version:             0.6.1
 Synopsis:            iteratees based upon mutable buffers
 Description:         Provides iteratees backed by mutable buffers.  This enables iteratees to run without any extra memory allocations.
 Homepage:            http://jwlato.webfactional.com/haskell/mutable-iter
diff --git a/src/Data/MutableIter.hs b/src/Data/MutableIter.hs
--- a/src/Data/MutableIter.hs
+++ b/src/Data/MutableIter.hs
@@ -20,14 +20,18 @@
   ,isStreamFinished
   ,head
   ,heads
+  ,chunk
   ,peek
   ,drop
   ,dropWhile
   ,foldl'
+  ,hopfoldl'
   ,mapStream
   ,mapChunk
   ,mapAccum
   ,convStream
+  ,unfoldConvStream
+  ,getChannel
   ,takeUpTo
   ,fromUVector
   ,enumHandleRandom
@@ -182,6 +186,14 @@
     step cnt s str = idone cnt str
 {-# INLINE heads #-}
 
+chunk ::
+  (MonadCatchIO m, Storable el)
+  => MIteratee (IOBuffer r el) m (IOBuffer r el)
+chunk = liftI step
+ where
+  step (I.Chunk buf) = guardNull buf (liftI step) $ idone buf (I.Chunk empty)
+  step str = MIteratee . I.throwErr . toException $ I.EofException
+
 drop :: (MonadCatchIO m, Storable el) => Int -> MIteratee (IOBuffer r el) m ()
 drop n = liftI (step n)
   where
@@ -218,7 +230,26 @@
     step acc str = idone acc str
 {-# INLINE foldl' #-}
 
+hopfoldl' :: (MonadCatchIO m, Storable el, Show a) =>
+  Int
+  -> (a -> el -> a)
+  -> a
+  -> MIteratee (IOBuffer r el) m a
+hopfoldl' hop f acc' = liftI (step 0 acc')
+  where
+    step ihop acc (I.Chunk buf) = guardNull buf (liftI (step ihop acc)) $ do
+      (newacc, numExtra) <- liftIO $ do
+        IB.drop ihop buf
+        buflen <- IB.length buf
+        let numExtra = buflen `rem` hop
+        res <- IB.hopfoldl' hop f acc buf
+        IB.drop numExtra buf
+        return (res,numExtra)
+      liftI (step (hop-numExtra) newacc)
+    step _ acc str = idone acc str
+{-# INLINE hopfoldl' #-}
 
+
 -- -----------------------------------------------------------
 -- Enumeratees
 
@@ -289,6 +320,37 @@
               maybe (step k) (idone (liftI k) . I.EOF . Just)
     step k = fi >>= convStream fi . k . I.Chunk
 
+-- |The most general stream converter.  Given a function to produce iteratee
+-- transformers and an initial state, convert the stream using iteratees
+-- generated by the function while continually updating the internal state.
+unfoldConvStream ::
+  (MonadCatchIO m, Storable eli, Storable elo)
+  => (acc -> MIteratee (IOBuffer r eli) m (acc, IOBuffer r elo))
+  -> acc
+  -> MEnumeratee (IOBuffer r eli) (IOBuffer r elo) m a
+unfoldConvStream f acc0 = eneeCheckIfDone (check acc0)
+  where
+    check acc k = isStreamFinished >>=
+                    maybe (step acc k) (idone (liftI k) . I.EOF . Just)
+    step acc k = f acc >>= \(acc', s') ->
+                    eneeCheckIfDone (check acc') . k . I.Chunk $ s'
+
+-- | Decimate a stream by taking every n'th element, starting at element "m".
+getChannel ::
+  (MonadCatchIO m, Storable el)
+  => Int
+  -> Int
+  -> MEnumeratee (IOBuffer r el) (IOBuffer r el) m a
+getChannel 1        _   = convStream chunk
+getChannel numChans chn = unfoldConvStream mkIter chn
+ where
+  mkIter drp = do
+    drop drp
+    buf <- chunk
+    tlen <- liftIO $ IB.length buf
+    newbuf <- liftIO $ IB.decimate numChans buf
+    return (tlen `rem` numChans, newbuf)
+
 takeUpTo :: (MonadCatchIO pr, Storable el) =>
   Int
   -> MEnumeratee (IOBuffer r el) (IOBuffer r el) pr a
@@ -312,7 +374,7 @@
 -- ---------------------------------------------
 -- drivers and enumerators
 
--- So users don't need to manually work with IOBuffers all the time
+-- | Convert a Vector iteratee to an MIteratee.  Slower but convenient.
 fromUVector :: (U.Unbox el, Storable el, MonadCatchIO m) =>
   I.Iteratee (U.Vector el) m a
   -> MIteratee (IOBuffer r el) m a
diff --git a/src/Data/MutableIter/IOBuffer.hs b/src/Data/MutableIter/IOBuffer.hs
--- a/src/Data/MutableIter/IOBuffer.hs
+++ b/src/Data/MutableIter/IOBuffer.hs
@@ -17,6 +17,9 @@
   ,mapBuffer
   ,mapAccumBuffer
   ,foldl'
+  ,hopfoldl'
+  ,hopfoldM
+  ,decimate
   ,castBuffer
   ,freeze
   ,thaw
@@ -297,6 +300,44 @@
     off <- peek po
     go (l-off) i0 (pb `advancePtr` off)
 {-# INLINE foldl' #-}
+
+hopfoldl' :: (Storable b) => Int -> (a -> b -> a) -> a -> IOBuffer r b -> IO a
+hopfoldl' hop f acc (IOBuffer 0 _ _) = return acc
+hopfoldl' hop f i0 buf = withBuf buf $ \l po pb ->
+  let go !n !acc p | n>0 = do
+        el <- peek p
+        go (n-1) (f acc el) (p `advancePtr` hop)
+      go _ acc _ = return acc
+  in do
+    off <- peek po
+    go (l-off `div` hop) i0 (pb `advancePtr` off)
+{-# INLINE hopfoldl' #-}
+
+hopfoldM :: (Storable b) => Int -> (a -> b -> IO a) -> a -> IOBuffer r b -> IO a
+hopfoldM hop f acc (IOBuffer 0 _ _) = return acc
+hopfoldM hop f i0 buf = withBuf buf $ \l po pb ->
+  let go !n !acc p | n>0 = do
+        el <- peek p
+        acc' <- f acc el
+        go (n-1) acc' (p `advancePtr` hop)
+      go _ acc _ = return acc
+  in do
+    off <- peek po
+    go ((l-off) `div` hop) i0 (pb `advancePtr` off)
+{-# INLINE hopfoldM #-}
+
+-- | Create a new buffer of every 'nth' element.  The original buffer is
+--   not altered.
+decimate :: Storable b => Int -> IOBuffer r b -> IO (IOBuffer r b)
+decimate _skp (IOBuffer 0 _ _) = return empty
+decimate skip buf = do
+  ln <- length buf
+  let newlen = ln `div` skip
+  bufp <- mallocForeignPtrArray newlen
+  withForeignPtr bufp $ \p' ->
+    hopfoldM skip (\p el -> poke p el >> return (p `advancePtr` 1)) p' buf
+  op <- newFp 0
+  return $ createIOBuffer newlen op bufp
 
 unsafeToForeignPtr :: IOBuffer r el -> (Int, ForeignPtr Int, ForeignPtr el)
 unsafeToForeignPtr (IOBuffer l po pb) = (l,po,pb)
