-- | WavPack metadata sub-blocks
module Codec.Audio.WavPack.Metadata
( Metadata(..)
- , SubBlock(..)
+ , SubBlock
, Dummy(..)
, Unknown(..)
import Data.Typeable
import Prelude.Unicode
+-- | Type class for every metadata sub-blocks.
class (Binary α, Eq α, Show α, Typeable α) ⇒ Metadata α where
+ -- | Get the metadata ID (mandatory).
metaID ∷ α → Word8
+ -- | Get the size of metadata (optional).
metaSize ∷ α → Word32
-
metaSize = fromIntegral ∘ L.length ∘ runPut ∘ put
+ -- | Cast a 'SubBlock' to this type of metadata (optional).
+ fromSubBlock ∷ SubBlock → Maybe α
+ fromSubBlock (SubBlock a) = cast a
+ -- | Wrap the metadata into 'SubBlock' (optional).
+ toSubBlock ∷ α → SubBlock
+ toSubBlock = SubBlock
+-- | An opaque sub-block container.
data SubBlock = ∀α. Metadata α ⇒ SubBlock α
+ deriving Typeable
+
+instance Metadata SubBlock where
+ metaID (SubBlock a) = metaID a
+ metaSize (SubBlock a) = metaSize a
+ fromSubBlock = Just
+ toSubBlock = id
instance Binary SubBlock where
put (SubBlock a)
isLarge = idWord .&. 0x80 ≢ 0
rawID = idWord .&. (complement 0x40) .&. (complement 0x80)
adj = if isOdd then -1 else 0
- size ← if isLarge then
- do sz0 ← getWord8
- sz1 ← getWord8
- sz2 ← getWord8
- return $ ( (fromIntegral sz2 `shiftL` 17) .|.
- (fromIntegral sz1 `shiftL` 9) .|.
- (fromIntegral sz0 `shiftL` 1)
- ) + adj
- else
- fmap ((+ adj) ∘ (`shiftL` 1) ∘ fromIntegral) getWord8
- subb ← getLazyByteString $ fromIntegral (size ∷ Word32)
+ size ← if isLarge then
+ do sz0 ← getWord8
+ sz1 ← getWord8
+ sz2 ← getWord8
+ return $ ( (fromIntegral sz2 `shiftL` 17) .|.
+ (fromIntegral sz1 `shiftL` 9) .|.
+ (fromIntegral sz0 `shiftL` 1)
+ ) + adj
+ else
+ fmap ((+ adj) ∘ (`shiftL` 1) ∘ fromIntegral) getWord8
+ subb ← getLazyByteString $ fromIntegral (size ∷ Word32)
return $ runGet (getSubBlock rawID) subb
where
getSubBlock ∷ Word8 → Get SubBlock
-- | Dummy metadata to pad WavPack blocks.
data Dummy
= Dummy {
- dumSize ∷ !Word32
+ dumSize ∷ Word32
}
deriving (Eq, Show, Typeable)
-- | Unknown but optional metadata found in the WavPack block.
data Unknown
= Unknown {
- unkID ∷ !Word8
+ unkID ∷ Word8
, unkData ∷ L.ByteString
}
deriving (Eq, Show, Typeable)