X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=wavpack.git;a=blobdiff_plain;f=Codec%2FAudio%2FWavPack%2FEntropy.hs;h=fc9b96d1709da9056a69172f8a4e8a56b887a146;hp=444fc17957b5b5b7f42fc1b50e4a4203ecb15a49;hb=fdf0906148007ee7b0cfe2b0665b4601143b169e;hpb=5f113a044d1a17a7313124802b58c91819bc54eb diff --git a/Codec/Audio/WavPack/Entropy.hs b/Codec/Audio/WavPack/Entropy.hs index 444fc17..fc9b96d 100644 --- a/Codec/Audio/WavPack/Entropy.hs +++ b/Codec/Audio/WavPack/Entropy.hs @@ -4,18 +4,68 @@ -- | FIXME module Codec.Audio.WavPack.Entropy ( EntropyData(..) + + , clearMedians + + , getMedian0 + , getMedian1 + , getMedian2 + + , incMedian0 + , decMedian0 + , incMedian1 + , decMedian1 + , incMedian2 + , decMedian2 ) where +import Control.Monad.ST +import Control.Monad.Unicode +import Data.Bits +import Data.STRef import Data.Word +import Prelude.Unicode -- | FIXME -data EntropyData +data EntropyData s = EntropyData { -- | Median log2 values for a channel. - edMedian ∷ !(Word32, Word32, Word32) + edMedian0 ∷ !(STRef s Word32) + , edMedian1 ∷ !(STRef s Word32) + , edMedian2 ∷ !(STRef s Word32) -- | FIXME - , edSlowLevel ∷ !Word32 + , edSlowLevel ∷ !(STRef s Word32) -- | FIXME - , edErrorLimit ∷ !Word32 + , edErrorLimit ∷ !(STRef s Word32) } - deriving (Eq, Show) + +clearMedians ∷ EntropyData s → ST s () +clearMedians e + = writeSTRef (edMedian0 e) 0 ≫ + writeSTRef (edMedian1 e) 0 ≫ + writeSTRef (edMedian2 e) 0 + +-- | The time constant of the 3 median level breakpoints +div0, div1, div2 ∷ Word32 +div0 = 128 -- 5/ 7 of samples +div1 = 64 -- 10/ 49 of samples +div2 = 32 -- 20/343 of samples + +-- | Retrieve the specified median breakpoint (without frac; min = 1) +getMedian0, getMedian1, getMedian2 ∷ EntropyData s → ST s Word32 +getMedian0 = fmap ((`shiftR` 4) ∘ (+ 1)) ∘ readSTRef ∘ edMedian0 +getMedian1 = fmap ((`shiftR` 4) ∘ (+ 1)) ∘ readSTRef ∘ edMedian1 +getMedian2 = fmap ((`shiftR` 4) ∘ (+ 1)) ∘ readSTRef ∘ edMedian2 + +-- | Update the specified median breakpoints. Note that the median is +-- incremented when the sample is higher than the median, else +-- decremented. They are designed so that the median will never drop +-- below 1 and the value is essentially stationary if there are 2 +-- increments for every 5 decrements. +incMedian0, decMedian0, incMedian1, decMedian1, incMedian2, decMedian2 ∷ EntropyData s → ST s () +incMedian0 = flip modifySTRef (\x → x + ((x + div0 ) `div` div0) ⋅ 5) ∘ edMedian0 +decMedian0 = flip modifySTRef (\x → x - ((x + (div0-2)) `div` div0) ⋅ 2) ∘ edMedian0 +incMedian1 = flip modifySTRef (\x → x + ((x + div1 ) `div` div1) ⋅ 5) ∘ edMedian1 +decMedian1 = flip modifySTRef (\x → x - ((x + (div1-2)) `div` div1) ⋅ 2) ∘ edMedian1 +incMedian2 = flip modifySTRef (\x → x + ((x + div2 ) `div` div2) ⋅ 5) ∘ edMedian2 +decMedian2 = flip modifySTRef (\x → x - ((x + (div2-2)) `div` div2) ⋅ 2) ∘ edMedian2