From: PHO Date: Thu, 21 Jul 2011 03:05:54 +0000 (+0900) Subject: Adhering to the declarative style is way too painful, especially when we are porting... X-Git-Url: https://git.cielonegro.org/gitweb.cgi?a=commitdiff_plain;h=cef5d71977963aba55fc3a3d8ab313f497fb1acf;p=wavpack.git Adhering to the declarative style is way too painful, especially when we are porting a horribly side-effectful C program to Haskell. Trust STRef. STRef is our friend. --- diff --git a/Codec/Audio/WavPack/Words.hs b/Codec/Audio/WavPack/Words.hs index 1321c07..6406d3e 100644 --- a/Codec/Audio/WavPack/Words.hs +++ b/Codec/Audio/WavPack/Words.hs @@ -23,15 +23,17 @@ efficient with this data and results in about 1.22 bits per sample. -} module Codec.Audio.WavPack.Words ( WordsData(..) - , getWordsLossless +-- , getWordsLossless ) where import Codec.Audio.WavPack.Entropy import Codec.Audio.WavPack.Internal +import Control.Monad.ST import Data.Bits import Data.Bitstream.Generic (Bitstream) import qualified Data.Bitstream.Generic as B import Data.Int +import Data.STRef import qualified Data.Vector.Generic as GV import qualified Data.Vector.Generic.Mutable as MV import Data.Vector.Generic.New (New) @@ -57,6 +59,7 @@ data WordsData -- 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. (Bitstream bs, GV.Vector v Int32) ⇒ Bool -- ^ Is the stream monaural? → WordsData @@ -232,28 +235,37 @@ getWordsLossless isMono w0 bs0 nSamples0 | isMono = w { wdEntropyData = (e, snd $ wdEntropyData w) } | n `testBit` 0 = w { wdEntropyData = (e, snd $ wdEntropyData w) } | otherwise = w { wdEntropyData = (fst $ wdEntropyData w, e) } +-} -- | Read a single unsigned value from the specified bitstream with a -- value from 0 to maxCode. If there are exactly a power of two number -- of possible codes then this will read a fixed number of bits; -- otherwise it reads the minimum number of bits and then determines -- whether another bit is needed to define the code. -readCode ∷ Bitstream bs ⇒ bs → Word32 → (# Word32, bs #) +readCode ∷ Bitstream bs ⇒ STRef s bs → Word32 → ST s Word32 {-# INLINEABLE readCode #-} -readCode bs 0 = (# 0, bs #) -readCode bs 1 = (# b2n (B.head bs), B.tail bs #) +readCode bs 0 = return 0 +readCode bs 1 = fmap b2n $ takeHead bs readCode bs maxCode - = let !bitCount = countBits maxCode - !extras = bit bitCount - maxCode - 1 - !code = B.toBits (B.take (bitCount - 1) bs) - (# code', bitCount' #) - = if code ≥ extras then - (# (code `shiftL` 1) - - extras - + b2n (bs B.!! bitCount) - , bitCount #) - else - (# code, bitCount - 1 #) - !bs' = B.drop bitCount' bs - in - (# code', bs' #) + = do let bitCount = countBits maxCode + extras = bit bitCount - maxCode - 1 + code ← takeBits bs (bitCount - 1) + if code ≥ extras then + do nextBit ← takeHead bs + return $ (code `shiftL` 1) - extras + b2n nextBit + else + return code + +takeHead ∷ Bitstream bs ⇒ STRef s bs → ST s Bool +{-# INLINEABLE takeHead #-} +takeHead bsr + = do bs ← readSTRef bsr + writeSTRef bsr (B.tail bs) + return (B.head bs) + +takeBits ∷ (Integral n, Bitstream bs, Bits a) ⇒ STRef s bs → n → ST s a +{-# INLINEABLE takeBits #-} +takeBits bsr n + = do bs ← readSTRef bsr + writeSTRef bsr (B.drop n bs) + return (B.toBits (B.take n bs))