3 , ExistentialQuantification
6 -- | WavPack metadata sub-blocks
7 module Codec.Audio.WavPack.Metadata
17 import Data.Binary.Get
18 import Data.Binary.Put
20 import qualified Data.ByteString.Lazy as L
22 import Prelude.Unicode
24 class (Binary α, Eq α, Show α, Typeable α) ⇒ Metadata α where
28 metaSize = fromIntegral ∘ L.length ∘ runPut ∘ put
30 data SubBlock = ∀α. Metadata α ⇒ SubBlock α
32 instance Binary SubBlock where
34 = let size = metaSize a
35 oddBit = if odd size then 0x40 else 0
36 largeBit = if size > 255 then 0x80 else 0
37 idWord = metaID a .|. oddBit .|. largeBit
41 -- Don't forget about the endianness.
42 do putWord8 $ fromIntegral $ (size `shiftR` 1) .&. 0xFF
43 putWord8 $ fromIntegral $ (size `shiftR` 9) .&. 0xFF
44 putWord8 $ fromIntegral $ (size `shiftR` 17) .&. 0xFF
46 putWord8 $ fromIntegral $ (size `shiftR` 1) .&. 0xFF
48 when (odd size) $ putWord8 0
50 get = do idWord ← getWord8
51 let isOdd = idWord .&. 0x40 ≢ 0
52 isLarge = idWord .&. 0x80 ≢ 0
53 rawID = idWord .&. (complement 0x40) .&. (complement 0x80)
54 adj = if isOdd then -1 else 0
55 size ← if isLarge then
59 return $ ( (fromIntegral sz2 `shiftL` 17) .|.
60 (fromIntegral sz1 `shiftL` 9) .|.
61 (fromIntegral sz0 `shiftL` 1)
64 fmap ((+ adj) ∘ (`shiftL` 1) ∘ fromIntegral) getWord8
65 subb ← getLazyByteString $ fromIntegral (size ∷ Word32)
66 return $ runGet (getSubBlock rawID) subb
68 getSubBlock ∷ Word8 → Get SubBlock
69 getSubBlock 0x00 = fmap SubBlock (get ∷ Get Dummy)
71 = if unknownID .&. 0x20 ≡ 0 then
72 fail ("Unknown WavPack metadata ID: " ⧺ show unknownID)
74 -- It's unknown but optional. We can safely ignore it.
75 fmap (SubBlock ∘ Unknown unknownID) getRemainingLazyByteString
77 instance Eq SubBlock where
78 (SubBlock a) == (SubBlock b)
81 instance Show SubBlock where
82 show (SubBlock a) = show a
84 -- | Dummy metadata to pad WavPack blocks.
89 deriving (Eq, Show, Typeable)
91 instance Metadata Dummy where
95 instance Binary Dummy where
96 put = putLazyByteString ∘ flip L.replicate 0x00 ∘ fromIntegral ∘ dumSize
97 get = fmap (Dummy ∘ fromIntegral) remaining
99 -- | Unknown but optional metadata found in the WavPack block.
103 , unkData ∷ L.ByteString
105 deriving (Eq, Show, Typeable)
107 instance Metadata Unknown where
109 metaSize = fromIntegral ∘ L.length ∘ unkData
111 instance Binary Unknown where
112 put = putLazyByteString ∘ unkData