+-- | Maximum consecutive 1s sent for /div/ data.
+limitOnes ∷ Num n ⇒ n
+{-# INLINE limitOnes #-}
+limitOnes = 16
+
+getOnesCount ∷ Num a ⇒ Word8 → a
+{-# INLINE getOnesCount #-}
+getOnesCount = fromIntegral ∘ UV.unsafeIndex oct ∘ fromIntegral
+ where
+ oct ∷ UV.Vector Word8
+ {-# NOINLINE oct #-}
+ oct = UV.fromList
+ [ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 0 - 15
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5 -- 16 - 31
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 32 - 47
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6 -- 48 - 63
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 64 - 79
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5 -- 80 - 95
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 96 - 111
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7 -- 112 - 127
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 128 - 143
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5 -- 144 - 159
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 160 - 175
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6 -- 176 - 191
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 192 - 207
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5 -- 208 - 223
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 -- 124 - 239
+ , 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 8 -- 240 - 255
+ ]
+
+-- | This is an optimized version of 'getWord' that is used for
+-- lossless only ('edErrorLimit' ≡ 0). Also, rather than obtaining a
+-- single sample, it can be used to obtain an entire buffer of either
+-- mono or stereo samples.
+getWordsLossless ∷ ∀bs v s. (Bitstream bs, MV.MVector v Int32)
+ ⇒ Bool -- ^ Is the stream monaural?
+ → WordsData s
+ → STRef s bs -- ^ WV bitstream
+ → Int -- ^ Number of samples to get
+ → ST s (v s Int32)
+{-# INLINEABLE getWordsLossless #-}
+getWordsLossless isMono w bs nSamples0
+ = do v ← MV.new nSamples
+ n ← runContT (for 0 (< nSamples) (+ 1) (loop v)) return
+ return $ MV.take n v
+ where
+ nSamples ∷ Int
+ nSamples = if isMono
+ then nSamples0
+ else nSamples0 ⋅ 2
+
+ -- Hey, this is way tooooo long...
+ loop ∷ v s Int32
+ → Int
+ → ContT Int (ST s) ()
+ → ContT Int (ST s) ()
+ → ContT Int (ST s) ()
+ loop v n break continue
+ = do let c | isMono = fst $ wdEntropyData w
+ | n `testBit` 0 = fst $ wdEntropyData w
+ | otherwise = snd $ wdEntropyData w
+ med00 ← lift $ readSTRef (edMedian0 $ fst $ wdEntropyData w)
+ hldZero ← lift $ readSTRef (wdHoldingZero w)
+ hldOne ← lift $ readSTRef (wdHoldingOne w)
+ med10 ← lift $ readSTRef (edMedian0 $ snd $ wdEntropyData w)
+ when (med00 < 2 ∧ hldZero ≡ False ∧ hldOne ≡ 0 ∧ med10 < 2) $
+ do zAcc ← lift $ readSTRef (wdZeroesAcc w)
+ if zAcc > 0 then
+ do lift $ modifySTRef (wdZeroesAcc w) ((-) 1)
+ when (zAcc > 1) $
+ do lift $ MV.unsafeWrite v n 0
+ continue
+ else
+ do cBits ← lift $ takeWhileLessThan id 33 bs
+
+ when (cBits ≡ 33) $
+ break