module Codec.Audio.WavPack.Block
( BlockHeader(..)
, BlockFlags(..)
+
+ , findNextHeader
)
where
import Data.Binary
import Data.Binary.Strict.BitGet (getBit, getAsWord8, runBitGet)
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
+import Prelude.Unicode
-- | The preamble to every block in both the .wv and .wvc files.
data BlockHeader
= BlockHeader {
- -- | size of entire block (minus 8, of course)
+ -- | size of entire block (excluding the header)
bhSize ∷ !Word32
-- | 0x402 to 0x410 are currently valid for decode
, bhVersion ∷ !Word16
-- | number of samples in this block (0 = no audio)
, bhBlockSamples ∷ !Word32
-- | various flags for id and decoding
- , bhFlags ∷ !BlockHeader
+ , bhFlags ∷ !BlockFlags
-- | crc for actual decoded data
, bhCRC ∷ !Word32
}
putWord8 118 -- 'v'
putWord8 112 -- 'p'
putWord8 107 -- 'k'
- putWord32le $ bhSize bh
+ putWord32le $ bhSize bh + 32 - 8
putWord16le $ bhVersion bh
putWord8 $ bhTrackNo bh
putWord8 $ bhIndexNo bh
flags ← get
crc ← getWord32le
return BlockHeader {
- bhSize = size
+ bhSize = size + 8 - 32
, bhVersion = version
, bhTrackNo = trackNo
, bhIndexNo = indexNo
, bfFalseStereo = falseStereo
}
return bf
+
+findNextHeader ∷ L.ByteString → (Maybe BlockHeader, L.ByteString)
+findNextHeader src
+ = case L.uncons src of
+ Nothing
+ → (Nothing, L.empty)
+
+ Just (119, src') -- 'w'
+ → let (header, rest) = L.splitAt 32 src
+ in
+ case L.length header ≡ 32 of
+ False
+ → (Nothing, L.empty)
+
+ True
+ → let Just (magicW, header' ) = L.uncons header
+ Just (magicV, header'' ) = L.uncons header'
+ Just (magicP, header''') = L.uncons header''
+ magicK = L.head header'''
+ in
+ if magicW ≡ 119 ∧ magicV ≡ 118 ∧ magicP ≡ 112 ∧ magicK ≡ 107 then
+ -- Found the magic 'wvpk'.
+ let bh = runGet get header
+ in
+ (Just bh, rest)
+ else
+ findNextHeader src'
+
+ Just (_, src')
+ → findNextHeader src'
--- /dev/null
+{-# LANGUAGE
+ UnicodeSyntax
+ #-}
+module Main where
+import Codec.Audio.WavPack.Block
+import qualified Data.ByteString.Lazy as L
+import System.Environment
+
+main ∷ IO ()
+main = do [wvFile] ← getArgs
+ wvStream ← L.readFile wvFile
+ showWvInfo wvStream
+
+showWvInfo ∷ L.ByteString → IO ()
+showWvInfo stream
+ = case findNextHeader stream of
+ (Just bh, _)
+ → print bh
+ _ → fail "Can't find any WavPack block headers."