4 -- | Data types for WavPack codec.
5 module Codec.Audio.WavPack.Types
11 import Data.Binary.BitPut (putBit, putNBits, runBitPut)
12 import Data.Binary.Get
13 import Data.Binary.Put
14 import qualified Data.Binary.Strict.BitGet as BG
15 import Data.Binary.Strict.BitGet (getBit, getAsWord8, runBitGet)
16 import qualified Data.ByteString as S
17 import qualified Data.ByteString.Lazy as L
19 -- | The preamble to every block in both the .wv and .wvc files.
22 -- | size of entire block (minus 8, of course)
24 -- | 0x402 to 0x410 are currently valid for decode
26 -- | track number (0 if not used, like now)
28 -- | track sub-index (0 if not used, like now)
30 -- | total samples for entire file, but this is only valid if
31 -- 'bhBlockIndex' == 0 and a value of -1 indicates unknown
33 , bhTotalSamples ∷ !Word32
34 -- | index of first sample in block relative to beginning of
35 -- file (normally this would start at 0 for the first block)
36 , bhBlockIndex ∷ !Word32
37 -- | number of samples in this block (0 = no audio)
38 , bhBlockSamples ∷ !Word32
39 -- | various flags for id and decoding
40 , bhFlags ∷ !BlockHeader
41 -- | crc for actual decoded data
46 instance Binary BlockHeader where
48 = do putWord8 119 -- 'w'
52 putWord32le $ bhSize bh
53 putWord16le $ bhVersion bh
54 putWord8 $ bhTrackNo bh
55 putWord8 $ bhIndexNo bh
56 putWord32le $ bhTotalSamples bh
57 putWord32le $ bhBlockIndex bh
58 putWord32le $ bhBlockSamples bh
60 putWord32le $ bhCRC bh
62 get = do skip 4 -- "wvpk"
67 totalSamples ← getWord32le
68 blockIndex ← getWord32le
69 blockSamples ← getWord32le
77 , bhTotalSamples = totalSamples
78 , bhBlockIndex = blockIndex
79 , bhBlockSamples = blockSamples
84 -- | Various flags for decoding blocks
88 bfBytesPerSample ∷ !Word8
89 -- | 'False' = stereo output; 'True' = mono output
91 -- | 'False' = lossless mode; 'True' = hybrid mode
93 -- | 'False' = true stereo; 'True' = joint stereo (mid/side)
94 , bfJointStereo ∷ !Bool
95 -- | 'False' = independent channels; 'True' = cross-channel
97 , bfCrossDecorr ∷ !Bool
98 -- | 'False' = flat noise spectrum in hybrid; 'True' = hybrid
100 , bfHybridShape ∷ !Bool
101 -- | 'False' = integer data; 'True' = floating point data
102 , bfFloatData ∷ !Bool
103 -- | 'True' = extended size integers (> 24-bit); 'False' =
105 , bfExtendedInt ∷ !Bool
106 -- | 'False' = hybrid mode parameters control noise level;
107 -- 'True' = hybrid mode parameters control bitrate
108 , bfHybridBitrate ∷ !Bool
109 -- | 'True' = hybrid noise balanced between channels
110 , bfHybridBalance ∷ !Bool
111 -- | 'True' = initial block in sequence (for multichannel)
112 , bfInitialBlock ∷ !Bool
113 -- | 'True' = final block in sequence (for multichannel)
114 , bfFinalBlock ∷ !Bool
115 -- | amount of data left-shift after decode (0-31 places)
116 , bfLeftShift ∷ !Word8
117 -- | maximum magnitude of decoded data (number of bits integers
119 , bfMaxMagnitude ∷ !Word8
120 -- | sampling rate (0x1111 = unknown/custom) (THINKME)
121 , bfSamplingRate ∷ !Word8
122 -- | 'True' = use IIR for negative hybrid noise shaping
123 , bfIIRShaping ∷ !Bool
124 -- | 'True' = false stereo (data is mono but output is stereo)
125 , bfFalseStereo ∷ !Bool
129 instance Binary BlockFlags where
131 = let bs = runBitPut $
132 do putBit False -- reserved
133 putBit $ bfFalseStereo bf
134 putBit $ bfIIRShaping bf
135 putNBits 2 (0 ∷ Word8) -- reserved
136 putNBits 4 $ bfSamplingRate bf
137 putNBits 5 $ bfMaxMagnitude bf
138 putNBits 5 $ bfLeftShift bf
139 putBit $ bfFinalBlock bf
140 putBit $ bfInitialBlock bf
141 putBit $ bfFinalBlock bf
142 putBit $ bfHybridBalance bf
143 putBit $ bfHybridBitrate bf
144 putBit $ bfExtendedInt bf
145 putBit $ bfFloatData bf
146 putBit $ bfHybridShape bf
147 putBit $ bfCrossDecorr bf
148 putBit $ bfJointStereo bf
151 putNBits 2 $ bfBytesPerSample bf - 1
153 putLazyByteString (L.reverse bs)
155 get = do bs ← getBytes 4
157 = runBitGet (S.reverse bs) $
158 do BG.skip 1 -- reserved
161 BG.skip 2 -- reserved
162 samplingRate ← getAsWord8 4
163 maxMagnitude ← getAsWord8 5
164 leftShift ← getAsWord8 5
166 initialBlock ← getBit
167 hybridBalance ← getBit
168 hybridBitrate ← getBit
176 bytesPerSample ← getAsWord8 2
178 bfBytesPerSample = bytesPerSample + 1
181 , bfJointStereo = jointStereo
182 , bfCrossDecorr = crossDecorr
183 , bfHybridShape = hybridShape
184 , bfFloatData = floatData
185 , bfExtendedInt = extendedInt
186 , bfHybridBitrate = hybridBitrate
187 , bfHybridBalance = hybridBalance
188 , bfInitialBlock = initialBlock
189 , bfFinalBlock = finalBlock
190 , bfLeftShift = leftShift
191 , bfMaxMagnitude = maxMagnitude
192 , bfSamplingRate = samplingRate
193 , bfIIRShaping = iirShaping
194 , bfFalseStereo = falseStereo