X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=wavpack.git;a=blobdiff_plain;f=Codec%2FAudio%2FWavPack%2FMetadata.hs;h=601d42e666b8d45b2e68be9b28b9424af5feafec;hp=77901f445aedf505ab7e4ce117ae026ebdd147c7;hb=79fe8094594b6b25d7d9c44bc128418d69f1da95;hpb=9128d47e1f753b82477535a1116b3a4f416243fc diff --git a/Codec/Audio/WavPack/Metadata.hs b/Codec/Audio/WavPack/Metadata.hs index 77901f4..601d42e 100644 --- a/Codec/Audio/WavPack/Metadata.hs +++ b/Codec/Audio/WavPack/Metadata.hs @@ -9,6 +9,9 @@ module Codec.Audio.WavPack.Metadata , SubBlock , Dummy(..) + , DecorrTerms(..) + , RIFFHeader(..) + , RIFFTrailer(..) , Unknown(..) ) where @@ -18,7 +21,9 @@ import Data.Binary.Get import Data.Binary.Put import Data.Bits import qualified Data.ByteString.Lazy as L +import Data.Int import Data.Typeable +import qualified Data.Vector.Unboxed as UV import Prelude.Unicode -- | Type class for every metadata sub-blocks. @@ -85,7 +90,10 @@ instance Binary SubBlock where return $ runGet (getSubBlock rawID) subb where getSubBlock ∷ Word8 → Get SubBlock - getSubBlock 0x00 = fmap SubBlock (get ∷ Get Dummy) + getSubBlock 0x00 = fmap SubBlock (get ∷ Get Dummy ) + getSubBlock 0x02 = fmap SubBlock (get ∷ Get DecorrTerms) + 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) @@ -117,6 +125,70 @@ instance Binary Dummy where put = putLazyByteString ∘ flip L.replicate 0x00 ∘ fromIntegral ∘ dumSize get = fmap (Dummy ∘ fromIntegral) remaining +-- | Decorrelation terms and deltas. +data DecorrTerms + = DecorrTerms { + -- | [ (term, delta) ] + dectVec ∷ !(UV.Vector (Int8, Int8)) + } + deriving (Eq, Show, Typeable) + +instance Metadata DecorrTerms where + metaID _ = 0x02 + metaSize = fromIntegral ∘ UV.length ∘ dectVec + +instance Binary DecorrTerms where + put = UV.mapM_ (putWord8 ∘ packDT) ∘ dectVec + where + packDT ∷ (Int8, Int8) → Word8 + packDT (term, δ) + = fromIntegral ( (term + 5 .&. 0x1F) + .|. + ((δ `shiftL` 5) .&. 0xE0) + ) + + get = do n ← remaining + vec ← UV.replicateM (fromIntegral n) $ fmap unpackDT getWord8 + -- THINKME: unpack.c(read_decorr_terms) reverses the + -- order only when they are decoding. I don't know why so + -- I leave it unreversed for now. + return $ DecorrTerms vec + where + unpackDT ∷ Word8 → (Int8, Int8) + unpackDT w + = let term = (fromIntegral $ w .&. 0x1F) - 5 + δ = fromIntegral $ (w `shiftR` 5) .&. 0x07 + in + (term, δ) + +-- | 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 { @@ -130,8 +202,7 @@ data Unknown instance Metadata Unknown where metaID = unkID - metaSize = fromIntegral ∘ L.length ∘ unkData instance Binary Unknown where put = putLazyByteString ∘ unkData - get = (⊥) + get = error "unsupported operation"