]> gitweb @ CieloNegro.org - wavpack.git/blob - Codec/Audio/WavPack/Entropy.hs
EntropyData s
[wavpack.git] / Codec / Audio / WavPack / Entropy.hs
1 {-# LANGUAGE
2     UnicodeSyntax
3   #-}
4 -- | FIXME
5 module Codec.Audio.WavPack.Entropy
6     ( EntropyData(..)
7
8     , clearMedian
9
10     , getMedian0
11     , getMedian1
12     , getMedian2
13
14     , incMedian0
15     , decMedian0
16     , incMedian1
17     , decMedian1
18     , incMedian2
19     , decMedian2
20     )
21     where
22 import Control.Monad.ST
23 import Control.Monad.Unicode
24 import Data.Bits
25 import Data.STRef
26 import Data.Word
27 import Prelude.Unicode
28
29 -- | FIXME
30 data EntropyData s
31     = EntropyData {
32         -- | Median log2 values for a channel.
33         edMedian0    ∷ !(STRef s Word32)
34       , edMedian1    ∷ !(STRef s Word32)
35       , edMedian2    ∷ !(STRef s Word32)
36         -- | FIXME
37       , edSlowLevel  ∷ !(STRef s Word32)
38         -- | FIXME
39       , edErrorLimit ∷ !(STRef s Word32)
40       }
41
42 clearMedian ∷ EntropyData s → ST s ()
43 clearMedian e
44     = writeSTRef (edMedian0 e) 0 ≫
45       writeSTRef (edMedian1 e) 0 ≫
46       writeSTRef (edMedian2 e) 0
47
48 -- | The time constant of the 3 median level breakpoints
49 div0, div1, div2 ∷ Word32
50 div0 = 128 --  5/  7 of samples
51 div1 =  64 -- 10/ 49 of samples
52 div2 =  32 -- 20/343 of samples
53
54 -- | Retrieve the specified median breakpoint (without frac; min = 1)
55 getMedian0, getMedian1, getMedian2 ∷ EntropyData s → ST s Word32
56 getMedian0 = fmap ((`shiftR` 4) ∘ (+ 1)) ∘ readSTRef ∘ edMedian0
57 getMedian1 = fmap ((`shiftR` 4) ∘ (+ 1)) ∘ readSTRef ∘ edMedian1
58 getMedian2 = fmap ((`shiftR` 4) ∘ (+ 1)) ∘ readSTRef ∘ edMedian2
59
60 -- | Update the specified median breakpoints. Note that the median is
61 -- incremented when the sample is higher than the median, else
62 -- decremented.  They are designed so that the median will never drop
63 -- below 1 and the value is essentially stationary if there are 2
64 -- increments for every 5 decrements.
65 incMedian0, decMedian0, incMedian1, decMedian1, incMedian2, decMedian2 ∷ EntropyData s → ST s ()
66 incMedian0 = flip modifySTRef (\x → x + ((x +  div0   ) `div` div0) ⋅ 5) ∘ edMedian0
67 decMedian0 = flip modifySTRef (\x → x - ((x + (div0-2)) `div` div0) ⋅ 2) ∘ edMedian0
68 incMedian1 = flip modifySTRef (\x → x + ((x +  div1   ) `div` div1) ⋅ 5) ∘ edMedian1
69 decMedian1 = flip modifySTRef (\x → x - ((x + (div1-2)) `div` div1) ⋅ 2) ∘ edMedian1
70 incMedian2 = flip modifySTRef (\x → x + ((x +  div2   ) `div` div2) ⋅ 5) ∘ edMedian2
71 decMedian2 = flip modifySTRef (\x → x - ((x + (div2-2)) `div` div2) ⋅ 2) ∘ edMedian2