]> gitweb @ CieloNegro.org - wavpack.git/blobdiff - Codec/Audio/WavPack/Entropy.hs
Done implementing getWordsLossless but not tested
[wavpack.git] / Codec / Audio / WavPack / Entropy.hs
index 444fc17957b5b5b7f42fc1b50e4a4203ecb15a49..f031d118d112342b25bf005b2e13234a04d0a502 100644 (file)
@@ -4,18 +4,83 @@
 -- | FIXME
 module Codec.Audio.WavPack.Entropy
     ( EntropyData(..)
+
+    , clearMedian
+
+    , getMedian0
+    , getMedian1
+    , getMedian2
+
+    , incMedian0
+    , decMedian0
+    , incMedian1
+    , decMedian1
+    , incMedian2
+    , decMedian2
     )
     where
+import Data.Bits
 import Data.Word
+import Prelude.Unicode
 
 -- | FIXME
 data EntropyData
     = EntropyData {
         -- | Median log2 values for a channel.
-        edMedian     ∷ !(Word32, Word32, Word32)
+        edMedian0    ∷ !Word32
+      , edMedian1    ∷ !Word32
+      , edMedian2    ∷ !Word32
         -- | FIXME
       , edSlowLevel  ∷ !Word32
         -- | FIXME
       , edErrorLimit ∷ !Word32
       }
     deriving (Eq, Show)
+
+clearMedian ∷ EntropyData → EntropyData
+{-# INLINE clearMedian #-}
+clearMedian e = e {
+                  edMedian0 = 0
+                , edMedian1 = 0
+                , edMedian2 = 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 → Word32
+{-# INLINE getMedian0 #-}
+{-# INLINE getMedian1 #-}
+{-# INLINE getMedian2 #-}
+getMedian0 e = (edMedian0 e `shiftR` 4) + 1
+getMedian1 e = (edMedian1 e `shiftR` 4) + 1
+getMedian2 e = (edMedian2 e `shiftR` 4) + 1
+
+-- | 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 → EntropyData
+incMedian0 e
+    = e { edMedian0 =
+              edMedian0 e + ((edMedian0 e +  div0   ) `div` div0) ⋅ 5 }
+decMedian0 e
+    = e { edMedian0 =
+              edMedian0 e - ((edMedian0 e + (div0-2)) `div` div0) ⋅ 2 }
+incMedian1 e
+    = e { edMedian1 =
+              edMedian1 e + ((edMedian1 e +  div1   ) `div` div1) ⋅ 5 }
+decMedian1 e
+    = e { edMedian1 =
+              edMedian1 e - ((edMedian1 e + (div1-2)) `div` div1) ⋅ 2 }
+incMedian2 e
+    = e { edMedian2 =
+              edMedian2 e + ((edMedian2 e +  div2   ) `div` div2) ⋅ 5 }
+decMedian2 e
+    = e { edMedian2 =
+              edMedian2 e - ((edMedian2 e + (div2-2)) `div` div2) ⋅ 2 }