Double 转换的 ByteString 表示

ByteString representation of a Double conversion

我正在编写我自己的 WAVE 使用 Conduit 的解析器,因此我可以通过管道一个接一个地传输值。

我通过 hGet 从 .wav 文件中获取样本(n 是该 wav 文件的每个样本的字节数):

bytes <- hGet h n

这为我提供了一个 ByteString,其中包含示例的 Double 值的表示形式。例如:

"172"表示-0.10212671756744385

"g82"表示-0.10209953784942627

"582"代表-0.10208618640899658

可能的值介于 -1 和 +1 之间。

有什么方便的方法可以做这个转换吗?有图书馆可以做到这一点吗?

我查看了 Haskell 的现有 WAVE 解析器。 Data.WAVE.wav 文件和 returns 样本解析为左对齐的 Int32 值。我找到了一个解决方法,我使用它的库函数将我的 ByteString 转换为左对齐的 Int32,然后使用库的 sampleToDouble 函数将其转换为 Double .这行得通,但我想知道是否有更直接的方法来解决这个问题。

另一种可能的解决方案是将 ByteString 转换为 [Word8] 并使用 ByteString.unpack,将 [Word8] 转换为 Word32,然后将此值转换为Float 使用 Data.Binary.IEEE754 中的转换函数。这是一个好的解决方案吗?一个问题是我目前不知道如何将 [Word8] 的四元素列表转换为 Word32。

这是我目前将 ByteString 转换为双精度的解决方案:

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)

我想知道是否可以更有效地完成此操作。