-- | 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 without odd-size bit nor large-block bit
+ -- (mandatory).
metaID ∷ α → Word8
+ -- | Get the size of metadata, excluding the metadata header
+ -- (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)
= let size = metaSize a
- oddBit = if odd size then 0x40 else 0
- largeBit = if size > 255 then 0x80 else 0
+ size' = size + 1
+ oddBit = if odd size then 0x40 else 0
+ largeBit = if size > 0x1FE then 0x80 else 0
idWord = metaID a .|. oddBit .|. largeBit
in
do putWord8 idWord
- if size > 255 then
+ if size > 0x1FE then
-- Don't forget about the endianness.
- do putWord8 $ fromIntegral $ (size `shiftR` 1) .&. 0xFF
- putWord8 $ fromIntegral $ (size `shiftR` 9) .&. 0xFF
- putWord8 $ fromIntegral $ (size `shiftR` 17) .&. 0xFF
+ do putWord8 $ fromIntegral $ (size' `shiftR` 1) .&. 0xFF
+ putWord8 $ fromIntegral $ (size' `shiftR` 9) .&. 0xFF
+ putWord8 $ fromIntegral $ (size' `shiftR` 17) .&. 0xFF
else
- putWord8 $ fromIntegral $ (size `shiftR` 1) .&. 0xFF
+ putWord8 $ fromIntegral $ (size' `shiftR` 1) .&. 0xFF
put a
when (odd size) $ putWord8 0
-- | Dummy metadata to pad WavPack blocks.
data Dummy
= Dummy {
- dumSize ∷ !Word32
+ -- | Must be less than 2^25 bytes long due to the limitation
+ -- of WavPack specification.
+ dumSize ∷ Word32
}
deriving (Eq, Show, Typeable)
-- | Unknown but optional metadata found in the WavPack block.
data Unknown
= Unknown {
- unkID ∷ !Word8
+ -- | The ID of this unknown metadata without odd-size bit nor
+ -- large-block bit.
+ unkID ∷ Word8
+ -- | Raw data; must be less than 2^25 bytes long.
, unkData ∷ L.ByteString
}
deriving (Eq, Show, Typeable)