8 module Codec.Audio.WavPack.Decorrelation
13 import Control.Monad.ST
17 import qualified Data.Strict as S
18 import qualified Data.Vector.Generic.Mutable as MV
19 import Prelude.Unicode
29 -- | The decorrelation term: @(term /= 0) && ((-3 <= term <= 8)
30 -- || (term == 17) || (term <= 18))@
32 -- | The decorrelation delta: @0 <= delta <= 8@
34 -- | The decorrelation weight for channel A: @-1024 <= weight <=
36 , dpWeightA ∷ !(STRef s Int16)
37 -- | The decorrelation weight for channel B: @-1024 <= weight <=
39 , dpWeightB ∷ !(S.Maybe (STRef s Int16))
40 -- | The decorrelation samples for channel A.
41 , dpSamplesA ∷ !(v s Int32)
42 -- | The decorrelation samples for channel B.
43 , dpSamplesB ∷ !(S.Maybe (v s Int32))
46 -- |General function to perform stereo decorrelation pass on specified
47 -- buffer (although since this is the reverse function it might
48 -- technically be called /correlation/ instead). This version handles
49 -- all sample resolutions and weight deltas. The dpSamplesX data is
50 -- *not* returned normalized for term values 1-8, so it should be
51 -- normalized if it is going to be used to call this function again.
52 decorrStereoPass ∷ ∀v s. MV.MVector v Int32
56 {-# INLINEABLE decorrStereoPass #-}
57 decorrStereoPass dp buffer
59 = flip mapM_ [0 .. (MV.length buffer `div` 2) - 1] $ \n →
60 do a0 ← MV.unsafeRead (dpSamplesA dp) 0
61 a1 ← MV.unsafeRead (dpSamplesA dp) 1
62 let samA = 2 ⋅ a0 - a1
63 MV.unsafeWrite (dpSamplesA dp) 1 a0
64 tmpA ← MV.unsafeRead buffer (n ⋅ 2)
69 applyWeight ∷ Int16 → Int32 → Int32
70 {-# INLINE applyWeight #-}
71 applyWeight weight sample
72 | sample `shiftR` 0xFFFF ≡ 0
73 = (fromIntegral weight ⋅ sample + 512) `shiftR` 10
75 = ( (((sample .&. 0xFFFF) ⋅ fromIntegral weight) `shiftR` 9) +
76 (((sample .&. complement 0xFFFF) `shiftR` 9) ⋅ fromIntegral weight) +