, SubBlock
, Dummy(..)
+ , RIFFHeader(..)
+ , RIFFTrailer(..)
, Unknown(..)
)
where
-- | Type class for every metadata sub-blocks.
class (Binary α, Eq α, Show α, Typeable α) ⇒ Metadata α where
- -- | Get the metadata ID (mandatory).
+ -- | Get the metadata ID without odd-size bit nor large-block bit
+ -- (mandatory).
metaID ∷ α → Word8
- -- | Get the size of metadata (optional).
+ -- | 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).
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
where
getSubBlock ∷ Word8 → Get SubBlock
getSubBlock 0x00 = fmap SubBlock (get ∷ Get Dummy)
+ getSubBlock 0x21 = fmap SubBlock (get ∷ Get RIFFHeader)
+ getSubBlock 0x22 = fmap SubBlock (get ∷ Get RIFFTrailer)
getSubBlock unknownID
= if unknownID .&. 0x20 ≡ 0 then
fail ("Unknown WavPack metadata ID: " ⧺ show unknownID)
put = putLazyByteString ∘ flip L.replicate 0x00 ∘ fromIntegral ∘ dumSize
get = fmap (Dummy ∘ fromIntegral) remaining
+-- | RIFF header for .wav files (before audio)
+data RIFFHeader
+ = RIFFHeader {
+ riffHeader ∷ L.ByteString
+ }
+ deriving (Eq, Show, Typeable)
+
+instance Metadata RIFFHeader where
+ metaID _ = 0x21
+
+instance Binary RIFFHeader where
+ put = putLazyByteString ∘ riffHeader
+ get = fmap RIFFHeader getRemainingLazyByteString
+
+-- | RIFF trailer for .wav files (after audio)
+data RIFFTrailer
+ = RIFFTrailer {
+ riffTrailer ∷ L.ByteString
+ }
+ deriving (Eq, Show, Typeable)
+
+instance Metadata RIFFTrailer where
+ metaID _ = 0x22
+
+instance Binary RIFFTrailer where
+ put = putLazyByteString ∘ riffTrailer
+ get = fmap RIFFTrailer getRemainingLazyByteString
+
-- | Unknown but optional metadata found in the WavPack block.
data Unknown
= Unknown {
- -- | The ID of this unknown metadata.
+ -- | 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
instance Metadata Unknown where
metaID = unkID
- metaSize = fromIntegral ∘ L.length ∘ unkData
instance Binary Unknown where
put = putLazyByteString ∘ unkData