问题
I'm writing my own WAVE
parser that uses Conduit so I can stream values, one by one, through a pipeline.
I get a sample from a .wav file via hGet
(n is the number of bytes per sample for that wav file):
bytes <- hGet h n
This gives me a ByteString with a representation of the Double value of the sample. E.g.:
"\131\237\242"
represents -0.10212671756744385
"g\238\242"
represents -0.10209953784942627
"\215\238\242"
represents -0.10208618640899658
.
The possible values are between -1 and +1.
Is there any convenient way to do this conversion? Is there a library available to do this?
I've taken a look at existing WAVE
parsers for Haskell. Data.WAVE parses a .wav
file and returns the samples as left-justified Int32
values. I've found a workaround where I use it's library functions to convert my ByteString
to a left-justified Int32
and then convert it to a Double
using the library's sampleToDouble
function. This works, but I'm wondering if there is a more direct way of solving this problem.
Another possible solution would be to convert the ByteString
to [Word8]
with ByteString.unpack
, convert [Word8]
to Word32
and then convert this value to a Float
using the conversion functions from Data.Binary.IEEE754. Would this be a good solution? One problem is that I currently don't know how to convert a four-element list of [Word8] to Word32.
回答1:
This is my current solution to turn the ByteString into a double:
convertNBytesLen :: [Word8] -> Int32
convertNBytesLen = foldr accum 0
where accum bs a = 256 * a + fromIntegral bs
bsToDouble :: S.ByteString -> Int -> Double
bsToDouble bs n = if intV >= 0
then fromIntegral intV / 2147483647
else - (fromIntegral intV / (-2147483648))
where intV = convertNBytesLen (S.unpack bs) `shift` (32 - 8 * n)
I'm wondering if this can be done in a more efficient manner.
来源:https://stackoverflow.com/questions/41143884/bytestring-representation-of-a-double-conversion