+-- | Decorrelation weights.
+data DecorrWeights
+ = DecorrWeights {
+ -- | For mono blocks, this is a weight vector for the single
+ -- channel. For stereo blocks, it's interleaved as A, B, A, B,
+ -- ...
+ decwVec ∷ !(UV.Vector Int16)
+ }
+ deriving (Eq, Show, Typeable)
+
+instance Metadata DecorrWeights where
+ metaID _ = 0x03
+ metaSize = fromIntegral ∘ UV.length ∘ decwVec
+
+instance Binary DecorrWeights where
+ put = UV.mapM_ (putWord8 ∘ packW) ∘ decwVec
+ where
+ packW ∷ Int16 → Word8
+ packW w
+ = let w' | w > 1024 = 1024
+ | w < -1024 = -1024
+ | otherwise = w
+ w'' | w' > 0 = w' - ((w' + 64) `shiftR` 7)
+ | otherwise = w'
+ w''' = (w'' + 4) `shiftR` 3
+ in
+ fromIntegral w'''
+ get = do n ← remaining
+ vec ← UV.replicateM (fromIntegral n) $ fmap unpackW getWord8
+ -- THINKME: the same caution as DecorrTerms, but never
+ -- try to reverse the vector simply. Think about the
+ -- interleaving.
+ return $ DecorrWeights vec
+ where
+ unpackW ∷ Word8 → Int16
+ unpackW w
+ = let w' ∷ Int8
+ w' = fromIntegral w
+ w'' ∷ Int16
+ w'' = (fromIntegral w') `shiftL` 3
+ w''' | w'' > 0 = w'' + ((w'' + 64) `shiftR` 7)
+ | otherwise = w''
+ in
+ w'''
+