7 module Codec.Audio.WavPack.Unpack
12 import Codec.Audio.WavPack.Block
13 import Codec.Audio.WavPack.Words
14 import Control.Monad.ST
16 import Data.Bitstream.Generic (Bitstream)
19 import qualified Data.Strict as S
20 import qualified Data.Vector.Generic.Mutable as MV
22 import Prelude.Unicode
25 data WavpackStream bs s
28 , wpsWVCBlock ∷ !(S.Maybe Block)
29 , wpsWordsData ∷ !(WordsData s)
30 , wpsMuteError ∷ !(STRef s Bool)
31 , wpsSampleIndex ∷ !(STRef s Word32)
32 , wpsWVBits ∷ !(STRef s bs)
33 , wpsWVCBits ∷ !(S.Maybe (STRef s bs))
36 -- |This monster actually unpacks the WavPack bitstream(s) into the
37 -- specified buffer as 32-bit integers or floats (depending on orignal
38 -- data). Lossy samples will be clipped to their original limits
39 -- (i.e. 8-bit samples are clipped to -128/+127) but are still
40 -- returned in longs. It is up to the caller to potentially reformat
41 -- this for the final output including any multichannel distribution,
42 -- block alignment or endian compensation.
43 unpackSamples ∷ ∀bs v s. (Bitstream bs, MV.MVector v Int32)
45 → Int -- ^ Number of channels.
46 → Int -- ^ Reduced number of channels (1 or 2).
47 → Word32 -- ^ Number of samples to get.
49 {-# INLINEABLE unpackSamples #-}
50 unpackSamples wps numChannels reducedChannels nSamples0
51 = do let hdr = blockHeader $ wpsWVBlock wps
53 muteLimit0 = (1 `shiftL` fromIntegral (bfMaxMagnitude flags)) + 2
54 muteLimit ∷ Int32 -- FIXME: Do we really need to explicitly type this?
56 | bfHybrid flags ∧ S.isNothing (wpsWVCBlock wps)
61 nSamples ← do idx ← readSTRef (wpsSampleIndex wps)
62 if idx + nSamples0 > bhBlockIndex hdr + bhBlockSamples hdr then
63 return $ bhBlockIndex hdr + bhBlockSamples hdr - idx
67 muteError ← readSTRef (wpsMuteError wps)
69 do v ← if reducedChannels ≡ 1 ∨ numChannels ≡ 1 ∨ bfMono flags then
70 MV.replicate (fromIntegral nSamples) 0
72 MV.replicate (fromIntegral nSamples ⋅ 2) 0
73 modifySTRef (wpsSampleIndex wps) (+ nSamples)
76 do v ← if S.isNothing (wpsWVCBlock wps) ∧ bfMono flags then
77 -- handle lossless or hybrid lossy mono data
78 fail "FIXME: unsupported stream type: monaural stream"
80 if S.isNothing (wpsWVCBlock wps) ∧ (¬) (bfMono flags) then
81 -- handle lossless or hybrid lossy stereo data
82 do v ← if bfHybrid flags then
83 fail "FIXME: unsupported stream type: lossy stereo stream"