5 module Codec.Audio.WavPack.Entropy
22 import Control.Monad.ST
23 import Control.Monad.Unicode
27 import Prelude.Unicode
32 -- | Median log2 values for a channel.
33 edMedian0 ∷ !(STRef s Word32)
34 , edMedian1 ∷ !(STRef s Word32)
35 , edMedian2 ∷ !(STRef s Word32)
37 , edSlowLevel ∷ !(STRef s Word32)
39 , edErrorLimit ∷ !(STRef s Word32)
42 clearMedians ∷ EntropyData s → ST s ()
44 = writeSTRef (edMedian0 e) 0 ≫
45 writeSTRef (edMedian1 e) 0 ≫
46 writeSTRef (edMedian2 e) 0
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
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
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